v8  9.0.257(node16.0.0)
V8 is Google's open source JavaScript engine
cross-thread-persistent.h
Go to the documentation of this file.
1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
6 #define INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
7 
8 #include <atomic>
9 
10 #include "cppgc/internal/persistent-node.h"
11 #include "cppgc/internal/pointer-policies.h"
12 #include "cppgc/persistent.h"
13 #include "cppgc/visitor.h"
14 
15 namespace cppgc {
16 
17 namespace internal {
18 
19 template <typename T, typename WeaknessPolicy, typename LocationPolicy,
20  typename CheckingPolicy>
22  public LocationPolicy,
23  private WeaknessPolicy,
24  private CheckingPolicy {
25  public:
26  using typename WeaknessPolicy::IsStrongPersistent;
27  using PointeeType = T;
28 
30 
32  const SourceLocation& loc = SourceLocation::Current())
33  : LocationPolicy(loc) {}
34 
36  std::nullptr_t, const SourceLocation& loc = SourceLocation::Current())
37  : LocationPolicy(loc) {}
38 
40  SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
41  : PersistentBase(s), LocationPolicy(loc) {}
42 
44  T* raw, const SourceLocation& loc = SourceLocation::Current())
45  : PersistentBase(raw), LocationPolicy(loc) {
46  if (!IsValid(raw)) return;
47  PersistentRegion& region = this->GetPersistentRegion(raw);
48  SetNode(region.AllocateNode(this, &Trace));
49  this->CheckPointer(raw);
50  }
51 
53  T& raw, const SourceLocation& loc = SourceLocation::Current())
54  : BasicCrossThreadPersistent(&raw, loc) {}
55 
56  template <typename U, typename MemberBarrierPolicy,
57  typename MemberWeaknessTag, typename MemberCheckingPolicy,
58  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
60  internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
61  MemberCheckingPolicy>
62  member,
63  const SourceLocation& loc = SourceLocation::Current())
64  : BasicCrossThreadPersistent(member.Get(), loc) {}
65 
67  const BasicCrossThreadPersistent& other,
68  const SourceLocation& loc = SourceLocation::Current())
70  // Invoke operator=.
71  *this = other;
72  }
73 
74  // Heterogeneous ctor.
75  template <typename U, typename OtherWeaknessPolicy,
76  typename OtherLocationPolicy, typename OtherCheckingPolicy,
77  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
79  const BasicCrossThreadPersistent<U, OtherWeaknessPolicy,
80  OtherLocationPolicy,
81  OtherCheckingPolicy>& other,
82  const SourceLocation& loc = SourceLocation::Current())
84  *this = other;
85  }
86 
89  const SourceLocation& loc = SourceLocation::Current()) noexcept {
90  // Invoke operator=.
91  *this = std::move(other);
92  }
93 
95  const BasicCrossThreadPersistent& other) {
96  PersistentRegionLock guard;
97  AssignUnsafe(other.Get());
98  return *this;
99  }
100 
101  template <typename U, typename OtherWeaknessPolicy,
102  typename OtherLocationPolicy, typename OtherCheckingPolicy,
103  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
105  const BasicCrossThreadPersistent<U, OtherWeaknessPolicy,
106  OtherLocationPolicy,
107  OtherCheckingPolicy>& other) {
108  PersistentRegionLock guard;
109  AssignUnsafe(other.Get());
110  return *this;
111  }
112 
114  if (this == &other) return *this;
115  Clear();
116  PersistentRegionLock guard;
117  PersistentBase::operator=(std::move(other));
118  LocationPolicy::operator=(std::move(other));
119  if (!IsValid(GetValue())) return *this;
120  GetNode()->UpdateOwner(this);
121  other.SetValue(nullptr);
122  other.SetNode(nullptr);
123  this->CheckPointer(GetValue());
124  return *this;
125  }
126 
128  Assign(other);
129  return *this;
130  }
131 
132  // Assignment from member.
133  template <typename U, typename MemberBarrierPolicy,
134  typename MemberWeaknessTag, typename MemberCheckingPolicy,
135  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
137  internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
138  MemberCheckingPolicy>
139  member) {
140  return operator=(member.Get());
141  }
142 
144  Clear();
145  return *this;
146  }
147 
149  Assign(s);
150  return *this;
151  }
152 
153  /**
154  * Returns a pointer to the stored object.
155  *
156  * Note: **Not thread-safe.**
157  *
158  * \returns a pointer to the stored object.
159  */
160  // CFI cast exemption to allow passing SentinelPointer through T* and support
161  // heterogeneous assignments between different Member and Persistent handles
162  // based on their actual types.
163  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
164  return static_cast<T*>(const_cast<void*>(GetValue()));
165  }
166 
167  /**
168  * Clears the stored object.
169  */
170  void Clear() {
171  // Simplified version of `Assign()` to allow calling without a complete type
172  // `T`.
173  const void* old_value = GetValue();
174  if (IsValid(old_value)) {
175  PersistentRegionLock guard;
176  PersistentRegion& region = this->GetPersistentRegion(old_value);
177  region.FreeNode(GetNode());
178  SetNode(nullptr);
179  }
180  SetValue(nullptr);
181  }
182 
183  /**
184  * Returns a pointer to the stored object and releases it.
185  *
186  * Note: **Not thread-safe.**
187  *
188  * \returns a pointer to the stored object.
189  */
190  T* Release() {
191  T* result = Get();
192  Clear();
193  return result;
194  }
195 
196  /**
197  * Conversio to boolean.
198  *
199  * Note: **Not thread-safe.**
200  *
201  * \returns true if an actual object has been stored and false otherwise.
202  */
203  explicit operator bool() const { return Get(); }
204 
205  /**
206  * Conversion to object of type T.
207  *
208  * Note: **Not thread-safe.**
209  *
210  * \returns the object.
211  */
212  operator T*() const { return Get(); } // NOLINT
213 
214  /**
215  * Dereferences the stored object.
216  *
217  * Note: **Not thread-safe.**
218  */
219  T* operator->() const { return Get(); }
220  T& operator*() const { return *Get(); }
221 
222  template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
223  typename OtherLocationPolicy = LocationPolicy,
224  typename OtherCheckingPolicy = CheckingPolicy>
225  BasicCrossThreadPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
226  OtherCheckingPolicy>
227  To() const {
228  PersistentRegionLock guard;
229  return BasicCrossThreadPersistent<U, OtherWeaknessPolicy,
230  OtherLocationPolicy, OtherCheckingPolicy>(
231  static_cast<U*>(Get()));
232  }
233 
234  template <typename U = T,
235  typename = typename std::enable_if<!BasicCrossThreadPersistent<
236  U, WeaknessPolicy>::IsStrongPersistent::value>::type>
238  Lock() const {
241  }
242 
243  private:
244  static bool IsValid(const void* ptr) {
245  return ptr && ptr != kSentinelPointer;
246  }
247 
248  static void Trace(Visitor* v, const void* ptr) {
249  const auto* handle = static_cast<const BasicCrossThreadPersistent*>(ptr);
250  v->TraceRoot(*handle, handle->Location());
251  }
252 
253  void Assign(T* ptr) {
254  const void* old_value = GetValue();
255  if (IsValid(old_value)) {
256  PersistentRegionLock guard;
257  PersistentRegion& region = this->GetPersistentRegion(old_value);
258  if (IsValid(ptr) && (&region == &this->GetPersistentRegion(ptr))) {
259  SetValue(ptr);
260  this->CheckPointer(ptr);
261  return;
262  }
263  region.FreeNode(GetNode());
264  SetNode(nullptr);
265  }
266  SetValue(ptr);
267  if (!IsValid(ptr)) return;
268  PersistentRegionLock guard;
269  SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
270  this->CheckPointer(ptr);
271  }
272 
273  void AssignUnsafe(T* ptr) {
274  PersistentRegionLock::AssertLocked();
275  const void* old_value = GetValue();
276  if (IsValid(old_value)) {
277  PersistentRegion& region = this->GetPersistentRegion(old_value);
278  if (IsValid(ptr) && (&region == &this->GetPersistentRegion(ptr))) {
279  SetValue(ptr);
280  this->CheckPointer(ptr);
281  return;
282  }
283  region.FreeNode(GetNode());
284  SetNode(nullptr);
285  }
286  SetValue(ptr);
287  if (!IsValid(ptr)) return;
288  SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
289  this->CheckPointer(ptr);
290  }
291 
292  void ClearFromGC() const {
293  if (IsValid(GetValue())) {
294  WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
296  }
297  }
298 
299  friend class cppgc::Visitor;
300 };
301 
302 template <typename T, typename LocationPolicy, typename CheckingPolicy>
303 struct IsWeak<
305  LocationPolicy, CheckingPolicy>>
306  : std::true_type {};
307 
308 } // namespace internal
309 
310 namespace subtle {
311 
312 /**
313  * **DO NOT USE: Has known caveats, see below.**
314  *
315  * CrossThreadPersistent allows retaining objects from threads other than the
316  * thread the owning heap is operating on.
317  *
318  * Known caveats:
319  * - Does not protect the heap owning an object from terminating.
320  * - Reaching transitively through the graph is unsupported as objects may be
321  * moved concurrently on the thread owning the object.
322  */
323 template <typename T>
324 using CrossThreadPersistent = internal::BasicCrossThreadPersistent<
326 
327 /**
328  * **DO NOT USE: Has known caveats, see below.**
329  *
330  * CrossThreadPersistent allows weakly retaining objects from threads other than
331  * the thread the owning heap is operating on.
332  *
333  * Known caveats:
334  * - Does not protect the heap owning an object from terminating.
335  * - Reaching transitively through the graph is unsupported as objects may be
336  * moved concurrently on the thread owning the object.
337  */
338 template <typename T>
339 using WeakCrossThreadPersistent = internal::BasicCrossThreadPersistent<
341 
342 } // namespace subtle
343 } // namespace cppgc
344 
345 #endif // INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(const BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
Definition: cross-thread-persistent.h:104
cppgc::internal::PersistentRegion::AllocateNode
PersistentNode * AllocateNode(void *owner, TraceCallback trace)
Definition: persistent-node.h:86
cppgc::internal::IsWeak
Definition: type-traits.h:36
cppgc::internal::BasicCrossThreadPersistent::Release
T * Release()
Definition: cross-thread-persistent.h:190
cppgc::internal::StrongCrossThreadPersistentPolicy
Definition: pointer-policies.h:116
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member)
Definition: cross-thread-persistent.h:136
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:52
cppgc::internal::SentinelPointer
Definition: sentinel-pointer.h:15
cppgc::subtle
Definition: cross-thread-persistent.h:310
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(const BasicCrossThreadPersistent &other, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:66
cppgc::internal::BasicCrossThreadPersistent::Clear
void Clear()
Definition: cross-thread-persistent.h:170
cppgc::internal::PersistentBase::SetValue
void SetValue(const void *value)
Definition: persistent.h:32
cppgc::internal::PersistentRegion::FreeNode
void FreeNode(PersistentNode *node)
Definition: persistent-node.h:97
cppgc::internal::PersistentBase::ClearFromGC
void ClearFromGC() const
Definition: persistent.h:39
cppgc::internal::WeakCrossThreadPersistentPolicy
Definition: pointer-policies.h:121
cppgc::internal::PersistentBase::GetValue
const void * GetValue() const
Definition: persistent.h:31
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:59
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(const BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:78
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(BasicCrossThreadPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
Definition: cross-thread-persistent.h:87
cppgc
Definition: allocation.h:17
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(std::nullptr_t)
Definition: cross-thread-persistent.h:143
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:31
cppgc::internal::PersistentBase
Definition: persistent.h:26
cppgc::internal::BasicCrossThreadPersistent::operator->
T * operator->() const
Definition: cross-thread-persistent.h:219
cppgc::internal::BasicCrossThreadPersistent::~BasicCrossThreadPersistent
~BasicCrossThreadPersistent()
Definition: cross-thread-persistent.h:29
cppgc::internal::PersistentBase::GetNode
PersistentNode * GetNode() const
Definition: persistent.h:34
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(const BasicCrossThreadPersistent &other)
Definition: cross-thread-persistent.h:94
cppgc::SourceLocation::Current
static constexpr SourceLocation Current()
Definition: source-location.h:43
cppgc::internal::BasicCrossThreadPersistent::Lock
BasicCrossThreadPersistent< U, internal::StrongCrossThreadPersistentPolicy > Lock() const
Definition: cross-thread-persistent.h:238
cppgc::internal::PersistentRegionLock::AssertLocked
static void AssertLocked()
cppgc::Visitor
Definition: visitor.h:52
cppgc::internal::BasicCrossThreadPersistent::operator*
T & operator*() const
Definition: cross-thread-persistent.h:220
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(std::nullptr_t, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:35
cppgc::internal::PersistentBase::SetNode
void SetNode(PersistentNode *node)
Definition: persistent.h:35
cppgc::internal::BasicCrossThreadPersistent::operator T*
operator T*() const
Definition: cross-thread-persistent.h:212
cppgc::kSentinelPointer
constexpr internal::SentinelPointer kSentinelPointer
Definition: sentinel-pointer.h:28
cppgc::Visitor::BasicCrossThreadPersistent
friend class internal::BasicCrossThreadPersistent
Definition: visitor.h:322
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(SentinelPointer s, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:39
cppgc::internal::BasicCrossThreadPersistent::operator bool
operator bool() const
Definition: cross-thread-persistent.h:203
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(SentinelPointer s)
Definition: cross-thread-persistent.h:148
cppgc::internal::BasicCrossThreadPersistent::BasicCrossThreadPersistent
BasicCrossThreadPersistent(T *raw, const SourceLocation &loc=SourceLocation::Current())
Definition: cross-thread-persistent.h:43
cppgc::internal
Definition: allocation.h:22
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(T *other)
Definition: cross-thread-persistent.h:127
cppgc::internal::BasicCrossThreadPersistent::operator=
BasicCrossThreadPersistent & operator=(BasicCrossThreadPersistent &&other)
Definition: cross-thread-persistent.h:113
cppgc::internal::BasicCrossThreadPersistent::To
BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > To() const
Definition: cross-thread-persistent.h:227
V8_CLANG_NO_SANITIZE
#define V8_CLANG_NO_SANITIZE(what)
Definition: v8config.h:478