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 MemberStorageType,
152 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
155 MemberCheckingPolicy, MemberStorageType>
169 template <
typename U,
typename OtherWeaknessPolicy,
170 typename OtherLocationPolicy,
typename OtherCheckingPolicy,
171 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
175 OtherCheckingPolicy>& other,
185 *
this = std::move(other);
191 AssignSafe(guard, other.Get());
195 template <
typename U,
typename OtherWeaknessPolicy,
196 typename OtherLocationPolicy,
typename OtherCheckingPolicy,
197 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
201 OtherCheckingPolicy>& other) {
203 AssignSafe(guard, other.Get());
208 if (
this == &other)
return *
this;
211 PersistentBase::operator=(std::move(other));
212 LocationPolicy::operator=(std::move(other));
213 if (!IsValid(
GetValue()))
return *
this;
217 this->CheckPointer(Get());
232 template <
typename U,
typename MemberBarrierPolicy,
233 typename MemberWeaknessTag,
typename MemberCheckingPolicy,
234 typename MemberStorageType,
235 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
238 MemberCheckingPolicy, MemberStorageType>
260 AssignSafe(guard, s);
275 return static_cast<T*
>(
const_cast<void*
>(
GetValue()));
283 AssignSafe(guard,
nullptr);
306 explicit operator bool()
const {
return Get(); }
315 operator T*()
const {
return Get(); }
325 template <
typename U,
typename OtherWeaknessPolicy = WeaknessPolicy,
326 typename OtherLocationPolicy = LocationPolicy,
327 typename OtherCheckingPolicy = CheckingPolicy>
331 using OtherBasicCrossThreadPersistent =
333 OtherCheckingPolicy>;
335 return OtherBasicCrossThreadPersistent(
336 typename OtherBasicCrossThreadPersistent::UnsafeCtorTag(),
337 static_cast<U*
>(Get()));
340 template <
typename U = T,
342 U, WeaknessPolicy>::IsStrongPersistent::value>::type>
350 static bool IsValid(
const void* ptr) {
354 static void TraceAsRoot(
RootVisitor& root_visitor,
const void* ptr) {
355 root_visitor.Trace(*
static_cast<const BasicCrossThreadPersistent*
>(ptr));
358 void AssignUnsafe(T* ptr) {
360 if (IsValid(old_value)) {
361 PersistentRegionLock guard;
365 if (IsValid(old_value)) {
366 CrossThreadPersistentRegion& region =
367 this->GetPersistentRegion(old_value);
368 if (IsValid(ptr) && (®ion == &this->GetPersistentRegion(ptr))) {
370 this->CheckPointer(ptr);
380 if (!IsValid(ptr))
return;
381 PersistentRegionLock guard;
382 SetNode(this->GetPersistentRegion(ptr).AllocateNode(
this, &TraceAsRoot));
383 this->CheckPointer(ptr);
386 void AssignSafe(PersistentRegionLock&, T* ptr) {
389 if (IsValid(old_value)) {
390 CrossThreadPersistentRegion& region =
391 this->GetPersistentRegion(old_value);
392 if (IsValid(ptr) && (®ion == &this->GetPersistentRegion(ptr))) {
394 this->CheckPointer(ptr);
401 if (!IsValid(ptr))
return;
402 SetNode(this->GetPersistentRegion(ptr).AllocateNode(
this, &TraceAsRoot));
403 this->CheckPointer(ptr);
406 void ClearFromGC()
const {
407 if (IsValid(GetValueFromGC())) {
408 WeaknessPolicy::GetPersistentRegion(GetValueFromGC())
416 T* GetFromGC()
const {
417 return static_cast<T*
>(
const_cast<void*
>(GetValueFromGC()));
423template <
typename T,
typename LocationPolicy,
typename CheckingPolicy>
426 LocationPolicy, CheckingPolicy>>
BasicCrossThreadPersistent & operator=(const BasicCrossThreadPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
friend class internal::RootVisitor
BasicCrossThreadPersistent & operator=(T *other)
BasicCrossThreadPersistent & operator=(std::nullptr_t)
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 & operator=(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy, MemberStorageType > member)
BasicCrossThreadPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
BasicCrossThreadPersistent(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy, MemberStorageType > member, 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, TraceRootCallback 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()
static constexpr SourceLocation Current()
#define CPPGC_DCHECK(condition)
constexpr internal::SentinelPointer kSentinelPointer
#define V8_CLANG_NO_SANITIZE(what)
defined(V8_TRIVIAL_ABI)