diff --git a/base/include/refbase.h b/base/include/refbase.h index c6f93daa7e9f08ad40daf85487d01e746e43e3d2..9d4316806624b26b35c842c844c60977e8afe030 100644 --- a/base/include/refbase.h +++ b/base/include/refbase.h @@ -18,6 +18,9 @@ #include #include +#ifdef DEBUG_REFBASE +#include +#endif namespace OHOS { @@ -25,6 +28,10 @@ namespace OHOS { class RefBase; +#ifdef DEBUG_REFBASE +class RefTracker; +#endif + class RefCounter { public: using RefPtrCallback = std::function; @@ -85,8 +92,60 @@ private: std::atomic atomicAttempt_; RefPtrCallback callback_ = nullptr; static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; +#ifdef DEBUG_REFBASE + RefTracker* refTracker = nullptr; + std::mutex trackerMutex; // To ensure refTracker be thread-safe + void GetNewTrace(const void* object); + void PrintTracker(); +#endif }; +#ifdef DEBUG_REFBASE +// RefTracker is a debug tool, used to record the trace of RefBase. +// RefTracker will save the information about the count of RefBase, +// including the pointer of sptr/wptr(The pointer of itself, not the pointer +// it manages), the amount of strong/weak/refcout and the PID&TID. +// The Tracker can live with RefCounter/RefBase(including its derivation). +// User should keep thread-safety of RefTracker. +class RefTracker { +public: + RefTracker() {}; + + RefTracker(RefTracker* exTracker, const void* id, int strong, + int weak, int ref, uint pid, uint tid); + + void GetTrace(RefTracker* exTracker, const void* id, int strong, + int weak, int ref, uint pid, uint tid); + + // Only used for tracking the amount of Strong Reference. + void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, + uint pid, uint tid); + + // Only used for tracking the amount of Weak Reference. + void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, + uint pid, uint tid); + + void PrintTrace(); + + void PrintStrongTrace(); + + void PrintWeakTrace(); + + RefTracker* GetexTrace(); + + RefTracker* PopTrace(); + +private: + const void* ptrID; + int strongRefCNT; + int weakRefCNT; + int refCNT; + uint PID; + uint TID; + RefTracker* exTrace; +}; +#endif + class WeakRefCounter { public: WeakRefCounter(RefCounter *base, void *cookie); diff --git a/base/src/refbase.cpp b/base/src/refbase.cpp index 1b2968ee190f15c56e8416d409fdcede2d830109..bfb36bfc06843d5f95ea69e82716429d4c7377f4 100644 --- a/base/src/refbase.cpp +++ b/base/src/refbase.cpp @@ -14,6 +14,10 @@ */ #include "refbase.h" +#ifdef DEBUG_REFBASE +#include "utils_log.h" +#include +#endif namespace OHOS { @@ -61,10 +65,102 @@ bool WeakRefCounter::AttemptIncStrongRef(const void *objectId) return refCounter_->AttemptIncStrongRef(objectId, unuse); } +#ifdef DEBUG_REFBASE +RefTracker::RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, uint pid, uint tid) + : ptrID (id), strongRefCNT (strong), weakRefCNT (weak), refCNT (ref), PID (pid), TID (tid), exTrace (exTracker) +{ +} + +void RefTracker::GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, uint pid, uint tid) +{ + ptrID = id; + strongRefCNT = strong; + weakRefCNT = weak; + refCNT = ref; + PID = pid; + TID = tid; + exTrace = exTracker; +} + +void RefTracker::GetStrongTrace(RefTracker* exTracker, const void* id, int strong, uint pid, uint tid) +{ + ptrID = id; + strongRefCNT = strong; + weakRefCNT = -(INITIAL_PRIMARY_VALUE); + refCNT = -(INITIAL_PRIMARY_VALUE); + PID = pid; + TID = tid; + exTrace = exTracker; +} + +void RefTracker::GetWeakTrace(RefTracker* exTracker, const void* id, int weak, uint pid, uint tid) +{ + ptrID = id; + strongRefCNT = -(INITIAL_PRIMARY_VALUE); + weakRefCNT = weak; + refCNT = -(INITIAL_PRIMARY_VALUE); + PID = pid; + TID = tid; + exTrace = exTracker; +} + +void RefTracker::PrintTrace() +{ + UTILS_LOGI("ptrID: %{public}016x strongcnt: %{public}d weakcnt: \ + %{public}d refcnt: %{public}d PID: %{public}d TID: %{public}d", \ + ptrID, strongRefCNT, weakRefCNT, refCNT, PID, TID); +} + +void RefTracker::PrintStrongTrace() +{ + UTILS_LOGI("ptrID: %{public}016x strongcnt: %{public}d \ + PID: %{public}d TID: %{public}d", ptrID, strongRefCNT,\ + PID, TID); +} + +void RefTracker::PrintWeakTrace() +{ + UTILS_LOGI("ptrID: %{public}016x weakcnt: %{public}d \ + PID: %{public}d TID: %{public}d", ptrID, weakRefCNT,\ + PID, TID); +} + +RefTracker* RefTracker::GetexTrace() +{ + return exTrace; +} + +RefTracker* RefTracker::PopTrace() +{ + RefTracker* ref = exTrace; + PrintTrace(); + delete this; + return ref; +} + +void RefCounter::GetNewTrace(const void* object) +{ + std::lock_guard lock(trackerMutex); + RefTracker* newTracker = new RefTracker(refTracker, object, atomicStrong_.load(std::memory_order_relaxed), + atomicWeak_.load(std::memory_order_relaxed), atomicRefCount_.load(std::memory_order_relaxed), + getpid(), gettid()); + refTracker = newTracker; +} + +void RefCounter::PrintTracker() +{ + std::lock_guard lock(trackerMutex); + while (refTracker) { + refTracker = refTracker->PopTrace(); + } +} +#endif + RefCounter::RefCounter() : atomicStrong_(INITIAL_PRIMARY_VALUE), atomicWeak_(0), atomicRefCount_(0), atomicFlags_(0), atomicAttempt_(0) { } + int RefCounter::GetRefCount() { return atomicRefCount_.load(std::memory_order_relaxed); @@ -101,12 +197,22 @@ bool RefCounter::IsRefPtrValid() RefCounter::~RefCounter() { +#ifdef DEBUG_REFBASE + while (refTracker) { + RefTracker* ref = refTracker; + ref->PrintTrace(); + refTracker = ref->GetexTrace(); + delete ref; + } +#endif } -int RefCounter::IncStrongRefCount(const void*) +int RefCounter::IncStrongRefCount(const void* object) { +#ifdef DEBUG_REFBASE + GetNewTrace(object); +#endif int curCount = atomicStrong_.load(std::memory_order_relaxed); - if (curCount >= 0) { curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed); if (curCount == INITIAL_PRIMARY_VALUE) { @@ -117,8 +223,11 @@ int RefCounter::IncStrongRefCount(const void*) return curCount; } -int RefCounter::DecStrongRefCount(const void*) +int RefCounter::DecStrongRefCount(const void* object) { +#ifdef DEBUG_REFBASE + GetNewTrace(object); +#endif int curCount = GetStrongRefCount(); if (curCount == INITIAL_PRIMARY_VALUE) { // unexpected case: there had never a strong reference. @@ -136,13 +245,19 @@ int RefCounter::GetStrongRefCount() return atomicStrong_.load(std::memory_order_relaxed); } -int RefCounter::IncWeakRefCount(const void*) +int RefCounter::IncWeakRefCount(const void* object) { +#ifdef DEBUG_REFBASE + GetNewTrace(object); +#endif return atomicWeak_.fetch_add(1, std::memory_order_relaxed); } -int RefCounter::DecWeakRefCount(const void*) +int RefCounter::DecWeakRefCount(const void* object) { +#ifdef DEBUG_REFBASE + GetNewTrace(object); +#endif int curCount = GetWeakRefCount(); if (curCount > 0) { curCount = atomicWeak_.fetch_sub(1, std::memory_order_release);