91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android的引用計數怎么實現

發布時間:2022-01-12 18:00:24 來源:億速云 閱讀:176 作者: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

德州市| 洞口县| 曲阜市| 棋牌| 米泉市| 渝中区| 九江市| 诏安县| 东至县| 安国市| 泸定县| 莱西市| 绥阳县| 基隆市| 平和县| 井冈山市| 大关县| 富川| 饶阳县| 常州市| 上栗县| 浮梁县| 大洼县| 无极县| 朔州市| 台北县| 金堂县| 淅川县| 阳春市| 满城县| 和平县| 龙南县| 玛多县| 崇仁县| 西乌| 鲁山县| 缙云县| 太白县| 宁阳县| 德昌县| 台南市|