chromium/mojo/public/cpp/base/shared_memory_version.h

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_VERSION_H_
#define MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_VERSION_H_

#include <stdint.h>

#include <atomic>

#include "base/component_export.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/structured_shared_memory.h"

namespace mojo {

class SharedMemoryVersionClient;

VersionType;

// This file contains classes to share a version between processes through
// shared memory. A version is a nonzero monotonically increasing integer. A
// controller has read and write access to the version and one or many clients
// have read access only. Controllers should only be created in privileged
// processes.
//
// Clients can avoid issuing IPCs depending on the version stored in shared
// memory. However this should only be used as a hint to avoid redundant IPC's,
// not to version other objects stored in shared memory: if the version
// increases, the client's copy of an object is out of date and it must fetch a
// fresh copy. But it couldn't use a copy of the object in shared memory and
// assume that it matches the updated version, because writes to the object and
// the version number can be reordered.
//
// Example:
//
//   class Controller : mojom::StateProvider {
//     ...
//
//     void SetState(State state) {
//       state_ = state;
//       version_.Increment();
//     }
//
//     void GetState(
//         base::OnceCallback<void(State, VersionType)> callback) override {
//       callback_.Run(state_, version_.GetSharedVersion());
//     }
//
//     SharedMemoryVersionController version_;
//   };
//
//   class Client {
//     ...
//
//     State GetState() {
//       // IPC can be avoided.
//       if (cached_version_ &&
//           !version_.SharedVersionIsGreaterThan(cached_version_)) {
//         return cached_state_.value();
//       }
//
//       State state;
//       VersionType version;
//
//       // Sync IPC to keep the example simple. Prefer async IPCs.
//       if (!provider_->GetState(&state, &version)) {
//         // error handling
//       }
//
//       cached_state_ = state;
//       cached_version_ = version;
//       return cached_state_.value();
//     }
//
//     mojo::Receiver<mojom::StateProvider> provider_;
//     std::optional<State> cached_state_;
//     std::optional<VersionType> cached_version_;
//     SharedMemoryVersionClient version_;
//
//   };

namespace shared_memory_version {

static constexpr VersionType kInvalidVersion =;
static constexpr VersionType kInitialVersion =;

}  // namespace shared_memory_version

// Used to modify the version number and issue read only handles to it.
class COMPONENT_EXPORT(MOJO_BASE) SharedMemoryVersionController {};

// Used to keep track of a remote version number and compare it to a
// locally tracked version.
class COMPONENT_EXPORT(MOJO_BASE) SharedMemoryVersionClient {};

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_VERSION_H_