Android 上C++对象的自动回收机制分析

3    : mRefs(new weakref_impl(this))
4 
5{};
4.       强引用计数和弱引用计数

在讨论智能指针前我们先考虑这样一种情况。假设A对象是由MA模块来创建和销毁的,MB模块的B对象增加A对象的引用计数来使用A对象,有一种情况 是:MA模块比MB模块提前被销毁,由于B对象使用着A,A的引用计数不为0,则A不会被销毁。在MA销毁后B继续使用A,假设A使用了MA模块的其他对 象或者资源,这时就会出问题,因为MA模块的其他对象或者资源已经销毁了。

为了解决上述问题,引用计数细分为强引用计数和弱引用计数。一般情况下,强引用计数控制着对象生命周期,如果强引用计数减为0时目标对象自动析构,即使弱引用计数不为0。弱引用计数后面介绍。

5.       sp和wp

前面说过,智能指针管理着对象的引用计数,Android中智能指针的实现是sp和wp。sp是strong pointer,wp是weak pointer。sp增加引用计数会分别将强引用计数和弱引用计数+1,wp增加引用计数时只会讲弱引用计数+1,。因此,弱引用计数总是 >= 强引用计数。sp可以保证目标对象一直是有效的,但wp不能保证,因此wp不能直接调用目标对象的方法,wp需要提升为sp后才能调用目标对象的方法。所 以wp没有提供指针操作符重载方法(operator* ()和operator->)。

sp和wp分别定义在

frameworks/base/include/utils/StrongPointer.h和frameworks/base/include/utils/RefBase.h文件。

sp对象构造调用incStrong

01template<typename T>
02 
03sp<T>::sp(T* other)
04 
05: m_ptr(other)
06 
07  {
08 
09    if (other) other->incStrong(this);
10 
11  }

incStrong将mStrong和mWeak分别加1,mStrong的值从INITIAL_STRONG_VALUE改为1

01void RefBase::incStrong(const void* id) const
02{
03    weakref_impl* const refs = mRefs;
04    refs->incWeak(id); // mWeak += 1
05    const int32_t c = android_atomic_inc(&refs->mStrong); // mStrong += 1
06    
07    if (c != INITIAL_STRONG_VALUE)  {
08        return;
09    }
10    
11    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
12}

sp对象析构调用decStrong

1template<typename T>
2sp<T>::~sp()
3{
4    if (m_ptr) m_ptr->decStrong(this);
5}

decStrong分别将mStrong和mWeak 减1,mStrong减为0时。如果mFlags的OBJECT_LIFETIME_STRONG被设置,调用delete this;析构目标对象。OBJECT_LIFETIME_STRONG是默认的情况,后面讨论。

01void RefBase::decStrong(const void* id) const
02{
03    
04    const int32_t c = android_atomic_dec(&refs->mStrong); // mStrong += 1
05    
06if (c == 1) {
07
08        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
09            delete this;
10        }
11    }
12    refs->decWeak(id); // mWeak -= 1
13}

wp对象的构造和析构过程也是类似的,构造时mWeak加1,析构时mWeak减1

6.       wp提升为sp的过程

wp对象调用promote方法返回sp对象,如果sp指向的对象已经销毁,promote返回NULL

1template<typename T>
2sp<T> wp<T>::promote() const
3{
4    sp<T> result;
5    if (m_ptr && m_refs->attemptIncStrong(&result)) {
6       result.set_pointer(m_ptr);
7    }
8    return result;
9}

可以将wp提升为sp的三种情况:

1、  没有sp指向目标对象且mStrong == INITIAL_STRONG_VALUE

2、  没有sp指向目标对象且mStrong == 0 且mFlags == OBJECT_LIFETIME_WEAK

3、有sp指向目标对象

attemptIncStrong()代码说明了上面的三种情况

01bool RefBase::weakref_type::attemptIncStrong(const void* id)
02 
03{
04 
05    incWeak(id);
06 
07    weakref_impl* const impl = static_cast<weakref_impl*>(this);
08 
09    int32_t curCount = impl->mStrong;
10 
11    LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
12 
13               this);
14 
15    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
16 
17        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
18 
19            break;
20 
21        }
22 
23        curCount = impl->mStrong;
24 
25    }
26 
27    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
28 
29        bool allow;
30 
31        if (curCount == INITIAL_STRONG_VALUE) {
32 
33            // Attempting to acquire first strong reference...  this is allowed
34 
35            // if the object does NOT have a longer lifetime (meaning the
36 
37            // implementation doesn't need to see this), or if the implementation
38 
39            // allows it to happen.
40 
41            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
42 
43                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
44 
45        } else {
46 
47            // Attempting to revive the object...  this is allowed
48 
49            // if the object DOES have a longer lifetime (so we can safely
50 
51            // call the object with only a weak ref) and the implementation
52 
53            // allows it to happen.
54 
55            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
56 
57                  && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
58        }
59        if (!allow) {
60            decWeak(id);
61            return false;
62        }
63 
64        curCount = android_atomic_inc(&impl->mStrong);
65        
66 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值