1 RefBase, sp, wp
在Android中,RefBase结合sp和wp,实现了一套通过引用计数的方法来控制对象生命周期的机制。
1.1 初识影子对象
refBase
是实现引用计数的基类,提供引用计数的方法。简单示例:
class A: public RefBase {
//..
}
int main() {
A* pA = new A;
{
//sp,wp对象是在{}中创建的,下面的代码先创建sp,然后创建wp
spspA(A);
wpwpA(spA);
//大括号结束前,先析构wp,再析构sp
}
}
1.1.1 RefBase和它的影子
示例代码中 class A
继承自RefBase
,使用的是RefBase
的构造函数
system/core/libutils/RefBase.cpp
RefBase::RefBase()
: mRefs(new weakref_impl(this)){
}
mRefs
是RefBase
的内部类weakref_type
的子类weakref_impl
的实例,保存在RefBase
中的一个字段。
class RefBase::weakref_impl : public RefBase::weakref_type {
public:
std::atomic mStrong;
std::atomic mWeak;
RefBase* const mBase;
std::atomic mFlags;
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
}
通过上面代码可知,在创建A
对象的同时也创建了一个weakref_type
对象,称为影子。
影子中的两个字段就关系对象的生死。
1.1.2 sp
system/core/include/utils/StrongPointer.h
继续查看实例代码中构造一个sp引用sp spA(A)
template
sp::sp(T* other)
: m_ptr(other) {
if (other)
other->incStrong(this);
}
其中T
必须继承自RefBase
,构建sp
引用后代码就执行了inctrong(this)
,该方法是RefBase
提供
system/core/libutils/RefBase.cpp
void RefBase::incStrong(const void* id) const {
//mRefs是RefBase中的字段,在RefBase构造函数执行时赋值
weakref_impl* const refs = mRefs;
//先增加弱引用计数
refs->incWeak(id);
//空实现,无视
refs->addStrongRef(id);
//原子操作,强引用增加1
const int32_t c = refs->mStrong.fetch_add(1,std::memory_order_relaxed);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
//判断是否为初识值
if (c != INITIAL_STRONG_VALUE) {
return;
}
//是第一引用就会执行下面的代码
//设置初识值
int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
/*如果是第一次引用,则调用onFirstRef()
这个函数很重要,派生类可以重载这个函数,完成一些初始化工作。*/
refs->mBase->onFirstRef();
}
incWeak(id)
函数
void RefBase::weakref_type::incWeak(const void* id) {
weakref_impl* const impl = static_cast(this);
//空实现,无视
impl->addWeakRef(id);
//原子操作,弱引用增加1
const int32_t c __unused = impl->mWeak.fetch_add(1,
std::memory_order_relaxed);
}
sp构造完成后RefBase
中weakref_impl
实例的强弱引用都增加了1.
wp
构造完成又是什么样的?
system/core/include/utils/RefBase.h
template
wp::wp(T* other)
: m_ptr(other) //m_ptr就是继承RefBase的实际对象
{
//调用pA的createWeak,并且保存返回值到成员变量m_refs中
if (other) m_refs = other->createWeak(this);
}
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
//mRefs就是那个new出来的weakref_impl实例
//增加弱引用加1
mRefs->incWeak(id);
return mRefs;
}
回到最初的示例代码,在构造完wp
后,A
对象的影子对象mRefs
中的mWeak
增加了2,mStrong
只增加了1。
wp
中有两个成员变量,一个保存实际对象,另一个保存影子对象。sp
只有一个成员变量用来保存实际对象,但这个实际对象内部已包含了对应的影子对象。
1.1.3 wp,sp析构
还是最初的回到实例代码里,我们是在代码块中创建的sp spA
和wp wpA
两个对象,更具代码的执行,除了代码块,两个对象的析构函数就会被调用。
system/core/include/utils/RefBase.h
wp::~wp()
{
//调用影子对象的decWeak,由影子对象的基类实现
if (m_ptr) m_refs->decWeak(this);
}
system/core/libutils/RefBase.cpp
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);
if (c != 1) return;
atomic_thread_fence(std::memory_order_acquire);
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
//如果c为1,则弱引用计数为0,这说明没用弱引用指向实际对象,需要考虑是否释放内存
// OBJECT_LIFETIME_XXX和生命周期有关系
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) {
// 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.
impl->mBase->onLastWeakRef(id);
delete impl->mBase;
}
}
继续示例代码,wp
析构后,弱引用计数为1,但是强引用也是1,所以不能释放对象。
sp析构:
system/core/include/utils/StrongPointer.h
sp::~sp() {
if (m_ptr)
//m_ptr就是实际对象,集成自RefBase
m_ptr->decStrong(this);
}
system/core/libutils/RefBase.cpp
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
//无视
refs->removeStrongRef(id);
//减一
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
refs);
if (c == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
//调用onLastStrongRef,表明强引用计数减为0,对象有可能被delete
refs->mBase->onLastStrongRef(id);
int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;
// The destructor does not delete refs in this case.
}
}
// Note that even with only strong reference operations, the thread
// deallocating this may not be the same as the thread deallocating refs.
// That's OK: all accesses to this happen before its deletion here,
// and all accesses to refs happen before its deletion in the final decWeak.
// The destructor can safely access mRefs because either it's deleting
// mRefs itself, or it's running entirely before the final mWeak decrement.
//weaktype_impl对象调用减少弱引用
refs->decWeak(id);
delete this
回调用被引用的析构函数,例如示例的A
类,如果强引用没有了,就把引用对象delete
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
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs;
}
} 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) = NULL;
}
sp
执行了减少强引用之后将执行减少弱引用,如果弱引用没有了。就把weaktype_impl
对象delete
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);
LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
this);
if (c != 1) 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) {
// 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影子对象
delete impl;
}
} else {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
impl->mBase->onLastWeakRef(id);
delete impl->mBase;
}
}
1.1.4 总结
RefBase
中有一个隐含的影子对象,这个对象就是实际包含被引用对象和强弱引用计数;
sp
构造引用后,强弱引用计数各增加1,sp
析构后,强弱引用计数各减1;
wp
构造引用后,弱引用增加1,wp
析构后,弱引用计数减1;
完全彻底地消灭RefBase对象,包括让实际对象和影子对象灭亡,这些都是由强弱引用计数控制的,另外还要考
虑flag的取值情况。当flag为0时,可得出如下结论:
- 强引用为0将导致实际对象被delete。
- 弱引用为0将导致影子对象被delete。
1.2 由弱生强
代码示例:
int main(){
A *pA =new A();
wp wpA(A);
sp spA = wpA.promote();//通过promote函数,得到一个sp。
}
1.2.1 由弱生强的方法
由示例代码可以看出,依靠函数promote()
可以得到一个sp
的对象
template
sp wp::promote() const
{
sp result;
//该函数就是弱生强的关键
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}
成败全靠attemptIncStrong()
system/core/libutils/RefBase.cpp
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id); //增加弱
weakref_impl* const impl = static_cast(this);
int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
//该循环在多线程操作同一个对象时会多次循环,他的目的就是让强引用加1
while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
// we're in the easy/common case of promoting a weak-reference
// from an existing strong reference.
if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)) {
break;
}
// the strong count has changed on us, we need to re-assert our
// situation. curCount was updated by compare_exchange_weak.
}
....//太长了,也看不懂,也是为了保证能装换强引用
if (curCount == INITIAL_STRONG_VALUE) {
impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
}
return true;
}
1.2.2 结果
结果当然就是强弱增加一个返回一个强引用对象。
1.3 生命周期的管理
在构造的sp
,或wp
的生命周期受flag的影响。
system/core/include/utils/RefBase.h
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
- 在flag为
OBJECT_LIFETIME_WEAK
时,即便sp
对象的强引用计数为0,而弱引用不为0,被引用对象不会被delete,进而在减少弱引用函数中再去判断,如果弱引用也为0了,就会delete掉被引用对象。 - 在flag为
OBJECT_LIFETIME_STRONG
强引用空之被引用对象的生命周期。弱引用控制影子对象的生命周期,强引用为0时,被引用对象delete。
1.3.1 轻量引用计数控制-LightRefBase
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;
...
private:
mutable std::atomic mCount;
};
这个类中仅有一个mCount
用来引用计数,使用也非常简单:
class A: public LightRefBase //泛型得是A
2 Thread类以及常用同步类
Thread类是Android为线程操作而做的一个封装。代码在Thread.cpp中,其中还封装了一些与线程同步相关的类
2.1 常见同步类
Android提供了两个封装好的同步类,它们是Mutex和Condition。这是重量级的同步技术,一般内核会有对应的
支持。另外,OS还提供了简单的原子操作,这些也算是同步技术的一种。
2.1.1 互斥类-Mutex
Mutex
的使用必须初始化,除此之外有两个重要函数处理同步,lock
(),unlock()
,分别表示开始上锁,释放锁。另外,Mutex
还提供了一个trylock()
函数,该函数只是尝试去锁住该区域,使用者需要根据trylock的返回值判
断是否成功锁住了该区域。
Mutex
类的内部还有一个AutoLock
帮助简化同步。
2.1.2 条件类-Condition
工作线程通过触发信号,唤起等待的进程。Condition
的信号触发需要在lock范围中才可以
3 Looper和Handler
工作原理:
一个消息队列,其他线程可以往这个队列中添加消息。
有一个消息循环,不断的去出消息,处理消息。![looper_handler-1]
在Android系统中:
Looper
用于封装消息循环,内部有一个消息队列
Handler
它是负责消息的入队和消息的处理。
Looper
中的消息队列里面存的是多个Message
每个Message
中有一个Handler
,用于处理Message
上一篇 《第四章 - Zygote》读书笔记