5#ifndef INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
6#define INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_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);
69template <
typename T,
typename WeaknessPolicy,
typename LocationPolicy,
70 typename CheckingPolicy>
72 public LocationPolicy,
73 private WeaknessPolicy,
74 private CheckingPolicy {
76 using typename WeaknessPolicy::IsStrongPersistent;
91 if (IsValid(old_value)) {
93 this->GetPersistentRegion(old_value);
107 : LocationPolicy(loc) {}
111 : LocationPolicy(loc) {}
120 if (!IsValid(raw))
return;
124 this->CheckPointer(raw);
130 template <
typename U,
typename OtherWeaknessPolicy,
131 typename OtherLocationPolicy,
typename OtherCheckingPolicy>
139 if (!IsValid(raw))
return;
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>>
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);
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) {
202 AssignSafe(guard, other.Get());
207 if (
this == &other)
return *
this;
210 PersistentBase::operator=(std::move(other));
211 LocationPolicy::operator=(std::move(other));
212 if (!IsValid(
GetValue()))
return *
this;
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>>
236 MemberCheckingPolicy>
258 AssignSafe(guard, s);
273 return static_cast<T*
>(
const_cast<void*
>(
GetValue()));
281 AssignSafe(guard,
nullptr);
304 explicit operator bool()
const {
return Get(); }
313 operator T*()
const {
return Get(); }
323 template <
typename U,
typename OtherWeaknessPolicy = WeaknessPolicy,
324 typename OtherLocationPolicy = LocationPolicy,
325 typename OtherCheckingPolicy = CheckingPolicy>
329 using OtherBasicCrossThreadPersistent =
331 OtherCheckingPolicy>;
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) {
353 const auto* handle =
static_cast<const BasicCrossThreadPersistent*
>(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()));
422template <
typename T,
typename LocationPolicy,
typename CheckingPolicy>
425 LocationPolicy, CheckingPolicy>>
static constexpr SourceLocation Current()
BasicCrossThreadPersistent & operator=(const BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
BasicCrossThreadPersistent(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent & operator=(T *other)
BasicCrossThreadPersistent & operator=(std::nullptr_t)
BasicCrossThreadPersistent & operator=(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member)
BasicCrossThreadPersistent(UnsafeCtorTag, T *raw, const SourceLocation &loc=SourceLocation::Current())
V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T *Get() const
BasicCrossThreadPersistent(const BasicCrossThreadPersistent &other, const SourceLocation &loc=SourceLocation::Current())
~BasicCrossThreadPersistent()
BasicCrossThreadPersistent & operator=(BasicCrossThreadPersistent &&other)
BasicCrossThreadPersistent(std::nullptr_t, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent(T *raw, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent(BasicCrossThreadPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
BasicCrossThreadPersistent< U, internal::StrongCrossThreadPersistentPolicy > Lock() const
BasicCrossThreadPersistent & operator=(SentinelPointer s)
BasicCrossThreadPersistent & operator=(const BasicCrossThreadPersistent &other)
BasicCrossThreadPersistent(SentinelPointer s, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent(const BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > To() const
BasicCrossThreadPersistent(const SourceLocation &loc=SourceLocation::Current())
V8_CLANG_NO_SANITIZE("address") const void *GetValueFromGC() const
PersistentNode * GetNodeSafe() const
void SetNodeSafe(PersistentNode *value) const
CrossThreadPersistentBase()=default
PersistentNode * GetNodeFromGC() const
CrossThreadPersistentBase(const void *raw)
V8_INLINE PersistentNode * AllocateNode(void *owner, TraceCallback trace)
V8_INLINE void FreeNode(PersistentNode *node)
const void * GetValue() const
void SetValue(const void *value)
PersistentNode * GetNode() const
void SetNode(PersistentNode *node)
void UpdateOwner(void *owner)
static void AssertLocked()
#define CPPGC_DCHECK(condition)
constexpr internal::SentinelPointer kSentinelPointer
#define V8_CLANG_NO_SANITIZE(what)