您的位置:首页 > 移动开发 > Android开发

Android中wp promote为sp流程

2015-09-17 13:54 393 查看
几个相关class的定义位置:

system/core$ vim include/utils/RefBase.h 其中定义了class wp

system/core/libutils/RefBase.cpp 其中定义了class RefBase::weakref_impl
system/core$ vim include/utils/StrongPointer.h 其中定义了class sp

以以下代码运行为例:

链接:http://blog.csdn.net/mfbao01/article/details/6255655

class WPTest : public RefBase {
public:
WPTest(){
LOGD("WPTest constructor");
}
virtual ~WPTest() {
LOGD("WPTest destructor");
}

virtual void onFirstRef() {
LOGD("first weak ptr ref callback");
}

virtual void onLastStrongRef(const void* id) {
LOGD("last strong ptr ref callback");
}

virtual void onLastWeakRef(const void* id) {
LOGD("last weak ptr ref callback");
}
};

int main()
{
WPTest *T = new WPTest();
{
wp<WPTest> weakp(T);

{
LOGD("promote to strong ptr.../n");

sp<WPTest> strongp = weakp.promote();

LOGD("strong ptr's lifetime is just about to finish .../n");
}

LOGD("weak ptr's lifetime is just about to finish .../n");
}

LOGD("weak ptr is out of scope./n");

return 0;
}


第一步:调用wp构造方法

system/core/include/utils/RefBase.h

template<typename T> template<typename U>
wp<T>::wp(U* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
m_refs为weakref_type类型的指针

上一步调了实例对像WPTest类的createWeak方法,但其中没有定义。对于用智能指针的类,都要继承类RefBase

此方法调的就是RefBase中的方法

system/core/libutils/RefBase.cpp

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);  //id为上面wp指针
return mRefs;
}

所以,m_refs = mRefs

mRefs是在RefBase构造方法中始初化的,RefBase构造方法为:

RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
所以mRefs->incWeak就是调用了weakref_impl中的方法,weakref_impl定义在

system/core/libutils/RefBase.cpp

class RefBase::weakref_impl : public RefBase::weakref_type
incWeak方法的实现在类weakref_type中

void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);    //将基类指针强制转换为派生类类型
impl->addWeakRef(id);     //调用派生类的实现    ---[1]---
const int32_t c = android_atomic_inc(&impl->mWeak);          ---[2]---
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
---[1]--- 先看看impl->addWeakRef(id)其中id是上面wp的this指针,也就是类wp的地址

void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak);
}
其中mWeakRefs为ref_entry结构体的指针,值为初始值NULL; mWeak为对像的引用计数值,为初始值0

void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);

ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
// update.  Positive value means we increment, negative--we
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
以上代码就是生成一个新的ref_entry结构用来存放对象的弱引用计数和wp的地址,新结构体放在最上面,也就是当前引用数和对应wp对象的一个记录信息

---[2]--- 下一步增加引用计数值,android_atomic_inc就是将impl中的mWeak变量数值加1,mWeak变量就是管理wp对象的引用计数

第二步:promote成强引用指针

system/core/include/utils/RefBase.h

template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}


这里就申明了一个强引用sp类对象result,m_refs上面说了是weakref_type指针

bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id);      //其中id为新创建sp类result的地址,它会新建个结构体保存当前引用计数值和sp地址加入链表,并将弱引用计数加1

weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong;

  ......

    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {                                   
        // we're now in the harder case of either:                                             
        // - there never was a strong reference on us                                          
        // - or, all strong references have been released                                      
        if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {                   
            // this object has a "normal" life-time, i.e.: it gets destroyed                   
            // when the last strong reference goes away                                        
            if (curCount <= 0) {                                                               
                // the last strong-reference got released, the object cannot                   
                // be revived.                                                                 
                decWeak(id);                                                                   
                return false;                                                                  
            }                                                                                  
                                                                                               
            // here, curCount == INITIAL_STRONG_VALUE, which means                             
            // there never was a strong-reference, so we can try to                            
            // promote this object; we need to do that atomically.                             
            while (curCount > 0) {
                if (android_atomic_cmpxchg(curCount, curCount + 1,                             
                        &impl->mStrong) == 0) {                                                
                    break;
                }                                                                              
                // the strong count has changed on us, we need to re-assert our                
                // situation (e.g.: another thread has inc/decStrong'ed us)
                curCount = impl->mStrong;
            }

    ......

    impl->addStrongRef(id);

#if PRINT_REFS
    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif

    // now we need to fix-up the count if it was INITIAL_STRONG_VALUE
    // this must be done safely, i.e.: handle the case where several threads
    // were here in attemptIncStrong().
    curCount = impl->mStrong;
    while (curCount >= INITIAL_STRONG_VALUE) {
        ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
                "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
                this);
        if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
                &impl->mStrong) == 0) {
            break;
        }
        // the strong-count changed on us, we need to re-assert the situation,
        // for e.g.: it's possible the fix-up happened in another thread.
        curCount = impl->mStrong;
    }

    return true;
}

 
impl->mStrong的初始值为INITIAL_STRONG_VALUE

#define INITIAL_STRONG_VALUE (1<<28)


impl->mFlags为0并没有设置OBJECT_LIFETIME_WEAK值

android_atomic_cmpxchg(curCount, curCount + 1, &impl->mStrong)中将impl->mStrong的值设为了curCount+1

之后再通过

android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
                &impl->mStrong)将curCount-INITIAL_STRONG_VALUE附给impl->mStrong, 实现强指针的计数。

$(".MathJax").remove();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: