5 #ifndef INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
6 #define INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
10 #include "cppgc/internal/persistent-node.h"
11 #include "cppgc/internal/pointer-policies.h"
12 #include "cppgc/persistent.h"
13 #include "cppgc/visitor.h"
43 return reinterpret_cast<std::atomic<PersistentNode*>*>(&
node_)->load(
44 std::memory_order_acquire);
50 #if defined(__has_feature
)
51 #if __has_feature
(address_sanitizer)
57 __atomic_store(&node_, &value, __ATOMIC_RELEASE);
61 reinterpret_cast<std::atomic<PersistentNode*>*>(&
node_)->store(
62 value, std::memory_order_release);
69 template <
typename T,
typename WeaknessPolicy,
typename LocationPolicy,
70 typename CheckingPolicy>
72 public LocationPolicy,
73 private WeaknessPolicy,
74 private CheckingPolicy {
76 using typename WeaknessPolicy::IsStrongPersistent;
77 using PointeeType = T;
86 PersistentRegionLock guard;
91 if (IsValid(old_value)) {
92 CrossThreadPersistentRegion& region =
93 this->GetPersistentRegion(old_value);
107 : LocationPolicy(loc) {}
111 : LocationPolicy(loc) {}
120 if (!IsValid(raw))
return;
121 PersistentRegionLock guard;
122 CrossThreadPersistentRegion& region =
this->GetPersistentRegion(raw);
124 this->CheckPointer(raw);
129 UnsafeCtorTag() =
default;
130 template <
typename U,
typename OtherWeaknessPolicy,
131 typename OtherLocationPolicy,
typename OtherCheckingPolicy>
139 if (!IsValid(raw))
return;
140 CrossThreadPersistentRegion& region =
this->GetPersistentRegion(raw);
142 this->CheckPointer(raw);
149 template <
typename U,
typename MemberBarrierPolicy,
150 typename MemberWeaknessTag,
typename MemberCheckingPolicy,
151 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
153 internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
154 MemberCheckingPolicy>
168 template <
typename U,
typename OtherWeaknessPolicy,
169 typename OtherLocationPolicy,
typename OtherCheckingPolicy,
170 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
174 OtherCheckingPolicy>& other,
184 *
this = std::move(other);
189 PersistentRegionLock guard;
190 AssignSafe(guard, other.Get());
194 template <
typename U,
typename OtherWeaknessPolicy,
195 typename OtherLocationPolicy,
typename OtherCheckingPolicy,
196 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
200 OtherCheckingPolicy>& other) {
201 PersistentRegionLock guard;
202 AssignSafe(guard, other.Get());
207 if (
this == &other)
return *
this;
209 PersistentRegionLock guard;
211 LocationPolicy::operator=(std::move(other));
214 other.SetValue(
nullptr);
215 other.SetNode(
nullptr);
216 this->CheckPointer(Get());
231 template <
typename U,
typename MemberBarrierPolicy,
232 typename MemberWeaknessTag,
typename MemberCheckingPolicy,
233 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
235 internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
236 MemberCheckingPolicy>
238 return operator=(member.Get());
257 PersistentRegionLock guard;
258 AssignSafe(guard, s);
273 return static_cast<T*>(
const_cast<
void*>(
GetValue()));
280 PersistentRegionLock guard;
281 AssignSafe(guard,
nullptr);
323 template <
typename U,
typename OtherWeaknessPolicy = WeaknessPolicy,
324 typename OtherLocationPolicy = LocationPolicy,
325 typename OtherCheckingPolicy = CheckingPolicy>
329 using OtherBasicCrossThreadPersistent =
331 OtherCheckingPolicy>;
332 PersistentRegionLock guard;
333 return OtherBasicCrossThreadPersistent(
334 typename OtherBasicCrossThreadPersistent::UnsafeCtorTag(),
335 static_cast<U*>(Get()));
338 template <
typename U = T,
340 U, WeaknessPolicy>::IsStrongPersistent::value>::type>
348 static bool IsValid(
const void* ptr) {
352 static void Trace(
Visitor* v,
const void* ptr) {
354 v->TraceRoot(*handle, handle->Location());
357 void AssignUnsafe(T* ptr) {
359 if (IsValid(old_value)) {
360 PersistentRegionLock guard;
364 if (IsValid(old_value)) {
365 CrossThreadPersistentRegion& region =
366 this->GetPersistentRegion(old_value);
367 if (IsValid(ptr) && (®ion == &
this->GetPersistentRegion(ptr))) {
369 this->CheckPointer(ptr);
379 if (!IsValid(ptr))
return;
380 PersistentRegionLock guard;
381 SetNode(this->GetPersistentRegion(ptr).AllocateNode(
this, &Trace)
);
382 this->CheckPointer(ptr);
385 void AssignSafe(PersistentRegionLock&, T* ptr) {
388 if (IsValid(old_value)) {
389 CrossThreadPersistentRegion& region =
390 this->GetPersistentRegion(old_value);
391 if (IsValid(ptr) && (®ion == &
this->GetPersistentRegion(ptr))) {
393 this->CheckPointer(ptr);
400 if (!IsValid(ptr))
return;
401 SetNode(this->GetPersistentRegion(ptr).AllocateNode(
this, &Trace)
);
402 this->CheckPointer(ptr);
405 void ClearFromGC()
const {
406 if (IsValid(GetValueFromGC())) {
407 WeaknessPolicy::GetPersistentRegion(GetValueFromGC())
415 T* GetFromGC()
const {
416 return static_cast<T*>(
const_cast<
void*>(GetValueFromGC()));
422 template <
typename T,
typename LocationPolicy,
typename CheckingPolicy>
425 LocationPolicy, CheckingPolicy>>
443 template <
typename T>
458 template <
typename T>