mirror of
https://github.com/openharmony/utils_native.git
synced 2026-07-21 01:25:42 -04:00
!88 Add a new feature for debugging refbase
Merge pull request !88 from JokerXD_liu/refbase_debug
This commit is contained in:
@@ -18,6 +18,9 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#ifdef DEBUG_REFBASE
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
|
||||
@@ -25,6 +28,10 @@ namespace OHOS {
|
||||
|
||||
class RefBase;
|
||||
|
||||
#ifdef DEBUG_REFBASE
|
||||
class RefTracker;
|
||||
#endif
|
||||
|
||||
class RefCounter {
|
||||
public:
|
||||
using RefPtrCallback = std::function<void()>;
|
||||
@@ -85,8 +92,60 @@ private:
|
||||
std::atomic<int> 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);
|
||||
|
||||
+120
-5
@@ -14,6 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "refbase.h"
|
||||
#ifdef DEBUG_REFBASE
|
||||
#include "utils_log.h"
|
||||
#include <unistd.h>
|
||||
#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<std::mutex> 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<std::mutex> 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);
|
||||
|
||||
Reference in New Issue
Block a user