From f568259a6cde3091eab9cd0b93f561eb4248c663 Mon Sep 17 00:00:00 2001 From: liujialiang Date: Wed, 9 Feb 2022 21:05:06 +0800 Subject: [PATCH] Anothor way to fix RefBase released repetitively by using atomic_flag. Signed-off-by: liujialiang --- base/include/refbase.h | 2 +- base/src/refbase.cpp | 40 +++++++++++----------------------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/base/include/refbase.h b/base/include/refbase.h index 4c4c24b..95cb816 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 a05709e..32b048e 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() -- Gitee