// 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_