温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android的引用计数怎么实现

发布时间:2022-01-12 18:00:24 来源:亿速云 阅读:231 作者:iii 栏目:互联网科技

本篇内容主要讲解“Android的引用计数怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android的引用计数怎么实现”吧!

1:问题

不像java这种runtime提供内存回收机制的语言,c c++开发中经常困扰开发者的是变量的分配与回收,当new完对象而忘记delete就会造成内存泄漏,如果delete了还在别处引用当对象,就会形成野指针

2:解决

一种内存回收策略叫引用计数,当对象被引用时,引用计数就+1,不再引用的时候引用计数就-1,当引用计数为0时,就回收对象。这种内存回收机制的问题是不能回收循环引用的对象,a对象有b对象的引用,同时b对象持有a对象的引用,就会出现a,b对象的引用数永远不可能为零的情况出现。

Android最简单的引用计数实现

template <class T> 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<const T*>(this);         }     }     //! DEBUGGING ONLY: Get current strong ref count.     inline int32_t getStrongCount() const {         return mCount.load(std::memory_order_relaxed);     }     typedef LightRefBase<T> 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<int32_t> mCount; };

仅仅是通过± mCount的值来进行判断变量是否还有引用引用,如果引用数降为零则会调用 delete static_cast<const T*>(this);析构函数

智能指针

sp strongPointer
wp weakPointer
这两个类的共同基类是refbase.cpp

使用场景:

在framework native 代码中经常会有如下用法

sp<ProcessState> proc = ProcessState::self(); sp<ProcessState> ProcessState::self() {     Mutex::Autolock _l(gProcessMutex);     if (gProcess != nullptr) {         return gProcess;     }     gProcess = new ProcessState(kDefaultDriver);     return gProcess; }

通过=操作符初始化sp

template<typename T> template<typename U> sp<T>& sp<T>::operator =(sp<U>&& other) {     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));     if (m_ptr) m_ptr->decStrong(this);     if (oldPtr != *const_cast<T* volatile*>(&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<int32_t>    mStrong;  //线程原子操作变量     std::atomic<int32_t>    mWeak;   //线程原子操作变量     RefBase* const          mBase;     std::atomic<int32_t>    mFlags;   //线程原子操作变量          explicit weakref_impl(RefBase* base)         : mStrong(INITIAL_STRONG_VALUE)         , mWeak(0)         , mBase(base)         , mFlags(0)     {     }

incWeak

void RefBase::weakref_type::incWeak(const void* id) {     weakref_impl* const impl = static_cast<weakref_impl*>(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); }

incStrong

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 }

decWeak

void RefBase::weakref_type::decWeak(const void* id) {     weakref_impl* const impl = static_cast<weakref_impl*>(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<weakref_impl*&>(mRefs) = nullptr; }

到此,相信大家对“Android的引用计数怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI