不像java这种runtime提供内存回收机制的语言,c c++开发中经常困扰开发者的是变量的分配与回收,当new完对象而忘记delete就会造成内存泄漏,如果delete了还在别处引用当对象,就会形成野指针
一种内存回收策略叫引用计数,当对象被引用时,引用计数就+1,不再引用的时候引用计数就-1,当引用计数为0时,就回收对象。这种内存回收机制的问题是不能回收循环引用的对象,a对象有b对象的引用,同时b对象持有a对象的引用,就会出现a,b对象的引用数永远不可能为零的情况出现。
(jvm虚拟机的采用的办法是通过扫描gcroot来判断对象是否被引用,想要深入了解可以看下下面的书籍)–《深入理解jvm虚拟机》
template
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
mCount.fetch_add(1, std::memory_order_relaxed);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete static_cast(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
typedef LightRefBase basetype;
protected:
inline ~LightRefBase() { }
private:
friend class ReferenceMover;
inline static void renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { }
inline static void renameRefId(T* /*ref*/, const void* /*old_id*/ , const void* /*new_id*/) { }
private:
mutable std::atomic mCount;
};
仅仅是通过± mCount的值来进行判断变量是否还有引用引用,如果引用数降为零则会调用 delete static_cast
sp strongPointer
wp weakPointer
这两个类的共同基类是refbase.cpp
在framework native 代码中经常会有如下用法
sp proc = ProcessState::self();
sp ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
return gProcess;
}
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
通过=操作符初始化sp
template template
sp& sp::operator =(sp&& other) {
T* oldPtr(*const_cast(&m_ptr));
if (m_ptr) m_ptr->decStrong(this);
if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
mptr是指向范性类型的指针 T*,T类型都是RefBase类型的派生类。如果之前有值会decStrong,并且将m_ptr指向新的RefBase类型的派生类
下面详细说下RefBase的incStrong与decStrong及WeakRef_type的incWeak与decWeak方法,整个引用计数计算方式及引用计数引起的对象构造,析构都围绕这四个方法展开。
特别关注
RefBase引用类型定义
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
及weakRef_impl类的四个成员变量
std::atomic mStrong; //线程原子操作变量
std::atomic mWeak; //线程原子操作变量
RefBase* const mBase;
std::atomic mFlags; //线程原子操作变量
explicit weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast(this);
impl->addWeakRef(id); //非debug模式什么也不做
const int32_t c __unused = impl->mWeak.fetch_add(1,
std::memory_order_relaxed); //impl变量mWeak线程安全模式+1
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); //若引用计数
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);// mStrong成员变量+1
if (c != INITIAL_STRONG_VALUE) { //如果不是第一次强引用计数+1则直接返回
return;
}
//如果是第一次则会把mStrong的初始值减去也就是使它的值 从1开始计算
int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef(); //第一次会回调onFirstRef
}
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast(this);
impl->removeWeakRef(id);
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //mWeak变量值线程安全-1
if (c != 1) return; //如果引用计数值>1及不止一个sp引用到这个变量,则return
//如果这是最后一个引用
atomic_thread_fence(std::memory_order_acquire);
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlives the object, it is not destroyed in the dtor, and
// we'll have to do it here.
if (impl->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {//如果mstrong是初始值,也就是没有执行过incStrong
// Decrementing a weak count to zero when object never had a strong
// reference. We assume it acquired a weak reference early, e.g.
// in the constructor, and will eventually be properly destroyed,
// usually via incrementing and decrementing the strong count.
// Thus we no longer do anything here. We log this case, since it
// seems to be extremely rare, and should not normally occur. We
// used to deallocate mBase here, so this may now indicate a leak.
ALOGW("RefBase: Object at %p lost last weak reference "
"before it had a strong reference", impl->mBase);
} else {
delete impl;
}
} else {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
//如果是弱引用并且是最后一个引用则会回调 onLastWeakRef方法
impl->mBase->onLastWeakRef(id);
delete impl->mBase; //析构对象本身
}
}
析构函数
RefBase::~RefBase()
{
int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
// Life-time of this object is extended to WEAK, in
// which case weakref_impl doesn't out-live the object and we
// can free it now.
if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
// It's possible that the weak count is not 0 if the object
// re-acquired a weak reference in its destructor
//如果是弱引用并且引用计数是0
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs; //析构impl类
}
} else if (mRefs->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// We never acquired a strong reference on this object.
LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
"RefBase: Explicit destruction with non-zero weak "
"reference count");
// TODO: Always report if we get here. Currently MediaMetadataRetriever
// C++ objects are inconsistently managed and sometimes get here.
// There may be other cases, but we believe they should all be fixed.
delete mRefs;
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast(mRefs) = nullptr;
}
1: 如果是强引用指向引用对象本身及调用sp构造函数,则会调用sp的incWeak,incStrong, mStrongRef ,mWeakRef值都会+1,如果是弱引用则 只有mWeakRef值会+1
2: 如果调用强引用对象的析构函数即 ~sp则会调用decWeak decStrong 强弱引用计数都会-1,只有引用计数减到0,才会析构对象本身及mBase变量