diff --git a/base/include/refbase.h b/base/include/refbase.h index 4c4c24b3cf2b6cac893b562ed349ac651fc880d2..95cb816a79dba425971b9e76348483c310fe0a71 100755 --- a/base/include/refbase.h +++ b/base/include/refbase.h @@ -28,7 +28,6 @@ class RefBase; class RefCounter { public: using RefPtrCallback = std::function; - friend class RefBase; RefCounter(); @@ -153,6 +152,7 @@ public: virtual bool OnAttemptPromoted(const void *objectId); private: + std::atomic_flag lock = ATOMIC_FLAG_INIT; RefCounter *refs_ = nullptr; }; diff --git a/base/src/refbase.cpp b/base/src/refbase.cpp index a05709e0840ed79f2c59422b9de6d7d1acc7cb27..32b048e4b15b333dc88abb55c2cbdd24edd86506 100755 --- a/base/src/refbase.cpp +++ b/base/src/refbase.cpp @@ -148,24 +148,11 @@ int RefCounter::DecWeakRefCount(const void*) curCount = atomicWeak_.fetch_sub(1, std::memory_order_release); } - if (curCount != 1) { - return curCount; - } - - if (IsLifeTimeExtended() && GetStrongRefCount() == 0) { + int strongRefCount = GetStrongRefCount(); + if (curCount == 1 || (strongRefCount == 0 && !IsLifeTimeExtended())) { if (callback_) { callback_(); } - } else { - // only weak ptr case: no strong reference, delete the object - if (GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { - if (callback_) { - callback_(); - } - } else { - // free RefCounter - delete (this); - } } return curCount; @@ -247,6 +234,7 @@ ATTEMPT_SUCCESS: RefBase::RefBase() : refs_(new RefCounter()) { + lock.clear(std::memory_order_release); refs_->IncRefCount(); refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); } @@ -254,6 +242,7 @@ RefBase::RefBase() : refs_(new RefCounter()) RefBase::RefBase(const RefBase &) { refs_ = new RefCounter(); + lock.clear(std::memory_order_release); if (refs_ != nullptr) { refs_->IncRefCount(); refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); @@ -262,6 +251,9 @@ RefBase::RefBase(const RefBase &) void RefBase::RefPtrCallback() { + if (lock.test_and_set(std::memory_order_acquire)) { + return; + } delete this; } @@ -279,6 +271,7 @@ RefBase &RefBase::operator=(const RefBase &) } refs_ = new RefCounter(); + lock.clear(std::memory_order_release); if (refs_ != nullptr) { refs_->IncRefCount(); refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); @@ -313,12 +306,7 @@ RefBase::~RefBase() { if (refs_ != nullptr) { refs_->RemoveCallback(); - if (refs_->IsLifeTimeExtended() && refs_->GetWeakRefCount() == 0) { - refs_->DecRefCount(); - } - if (refs_->GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { - delete refs_; - } + refs_->DecRefCount(); refs_ = nullptr; } } @@ -352,18 +340,12 @@ void RefBase::DecStrongRef(const void *objectId) return; } - RefCounter *const refs = refs_; - const int curCount = refs->DecStrongRefCount(objectId); + const int curCount = refs_->DecStrongRefCount(objectId); if (curCount == 1) { OnLastStrongRef(objectId); - if (!refs->IsLifeTimeExtended()) { - if (refs->callback_) { - refs->callback_(); - } - } } - refs->DecWeakRefCount(objectId); + DecWeakRef(objectId); } int RefBase::GetSptrRefCount()