File: shared_memory_version.h

package info (click to toggle)
chromium 135.0.7049.95-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,959,392 kB
  • sloc: cpp: 34,198,526; ansic: 7,100,035; javascript: 3,985,800; python: 1,395,489; asm: 896,754; xml: 722,891; pascal: 180,504; sh: 94,909; perl: 88,388; objc: 79,739; sql: 53,020; cs: 41,358; fortran: 24,137; makefile: 22,501; php: 13,699; tcl: 10,142; yacc: 8,822; ruby: 7,350; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; awk: 197; sed: 36
file content (156 lines) | stat: -rw-r--r-- 5,258 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// 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 <optional>

#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;

using VersionType = uint64_t;

// 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.
//
// Shared memory allocation can fail like any allocation. In that case it's not
// always possible to know why. When that happens classes in this file default
// to consistently falling back on IPCs.
//
// 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 = 0ULL;
static constexpr VersionType kInitialVersion = 1ULL;

}  // namespace shared_memory_version

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

  // Not copyable or movable
  SharedMemoryVersionController(const SharedMemoryVersionController&) = delete;
  SharedMemoryVersionController& operator=(
      const SharedMemoryVersionController&) = delete;

  // Get a shared memory region to be sent to a different process. It will be
  // used to instantiate a SharedMemoryVersionClient.
  base::ReadOnlySharedMemoryRegion GetSharedMemoryRegion() const;

  VersionType GetSharedVersion() const;

  // Increment shared version. This is not expected to cause a wrap of the value
  // during normal operation. This invariant is guaranteed with a CHECK.
  void Increment();

  // Directly set shared version. `version` must be strictly larger than
  // previous version. `version` cannot be maximum representable value for
  // VersionType.
  void SetVersion(VersionType version);

 private:
  std::optional<base::AtomicSharedMemory<VersionType>> mapped_region_;
};

// Used to keep track of a remote version number and compare it to a
// locally tracked version.
class COMPONENT_EXPORT(MOJO_BASE) SharedMemoryVersionClient {
 public:
  explicit SharedMemoryVersionClient(
      base::ReadOnlySharedMemoryRegion shared_region);
  ~SharedMemoryVersionClient();

  // Not copyable or movable
  SharedMemoryVersionClient(const SharedMemoryVersionClient&) = delete;
  SharedMemoryVersionClient& operator=(const SharedMemoryVersionClient&) =
      delete;

  // These functions can be used to form statements such as:
  // "Skip the IPC if `SharedVersionIsLessThan()` returns true."
  // The functions err on the side of caution and return true if the comparison
  // is impossible since issuing an IPC should always be an option.
  bool SharedVersionIsLessThan(VersionType version) const;
  bool SharedVersionIsGreaterThan(VersionType version) const;

 private:
  // Returns the current value in shared memory.
  VersionType GetSharedVersion() const;

  const std::optional<base::AtomicSharedMemory<VersionType>::ReadOnlyMapping>
      read_only_mapping_;
};

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_VERSION_H_