几个重要的概念
C++中对象的构造和稀构是自动的,对象的创建和释放需要new 和 delete来完成,因此用对象的构造和稀构来完成对象的引用和释放,将可以实现智能指针技术。
智能指针是一个对象,而不是一个指针。
对象的生命周期需要引用计数器来维护,每当有一个新的指针指向这个对象,这个对象的引用计数就+1,当一个指针不再指向这个对象,这个对象的引用计数就减一,当对象的引用计数为0时,所占的内存就可以安全释放。
简单的引用计数器不能解决循环引用的问题。
A 引用 B ,B 引用 A,的时候,A不再使用,但是B引用着A,A不能释放。同理 B被A引用 ,B也不能释放。如果把引用分为强引用和弱引用,将引用关系方向化,父-子,子-父,则规定:父引用子为强引用,子引用父为弱引用,当子引用父的时候及弱引用,父对象不再使用时,父对象生命周期的销毁不受子对象的约束。当释放了父对象,父对子的计数器也会被释放;当子不再使用的时候,子也就安全释放了,因为没有父对象对他进行强引用。总而言之就是:不能释放被强引用的对象,可以释放被弱引用的对象。
被弱引用的对象不能被直接使用,需要升级为强引用
如果一个对象A被B弱引用,因为A对象的销毁不受B控制,所以B不知道A是否销毁,就不能对A直接使用,需要将对A的弱引用升级为强引用之后才能使用。如果不能升级,说明A对象已经释放。
C++提供的三种智能指针 Light Pointer ,Strong Pointer, Weak Pointer
Light Pointer 轻量级指针使用的就是简单的引用技术,不能解决循环引用的问题。
所以支持智能指针的对象都需要对引用的对象进行计数。所以所有类都需要继承一个公共的引用技术类。 不同智能指针继承的公共引用计数类不同。
同时 Webkit 中的智能指针 和Chromium 中的智能指针和 Android系统源代码中的智能指针都有区别。
Light Pointer 轻量级指针
在源代码目录结构:
coffee@ubuntu:~/Android/frameworks/rs/cpp/util$ ls
RefBase.h StrongPointer.h TypeHelpers.h
RefBase.h 中一个内部类: LightRefBase 轻量级指针的引用计数类就是LightRefBase 强指针的引用计数类为RefBase
class LightRefBase1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30//.... RefBase ...
// -----------------------------------------------------------------------
template <class T>
class LightRefBase {
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
__sync_fetch_and_add(&mCount, 1);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (__sync_fetch_and_sub(&mCount, 1) == 1) {
delete static_cast<const T*>(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
}
typedef LightRefBase<T> basetype;
protected:
inline ~LightRefBase() { }
friend class ReferenceMover;
inline static void moveReferences(void*, void const*, size_t,
const ReferenceConverterBase&) { }
private:
mutable volatile int32_t mCount;
}; // ---------------------------------------------------------------------------
// ... RefBase ...
LightRefBase 只有一个成员变量 int32_t 类型的 mCount 用来描述一个对象的引用计数。
incStrong 内联函数用来增加引用计数
desStrong 内联函数用来减少引用计数
如果引用计数减少后为0,表示释放这个对象所占用的内存。
轻量级指针的实现是sp,同时也是 强指针 的实现类。
sp 其本身也是一个模板类
通过RefBase::weakref_type来实现引用计数
m_ptr 为成员变量,指向实际引用的对象。
包含 构造函数和拷贝构造函数,两个都对指向的对象执行从父类继承的incStrong操作。从而增加引用计数。
轻量级指针的使用使用举列:
1 |
|
强指针 弱指针
轻量级指针不能解决循环引用的问题,需要强指针和弱指针的概念,强指针和弱指针的关系比较密切,需要配合使用,同时 RefBase 相对于 LightRefBase 复杂,解决了更多问题。
和轻量级指针的相同点:都用incStrong ,desStrong 来操作引用计数器。但是引用计数器又有强指针和弱指针的概念,轻量级指针仅仅通过整形变量mutable volatile int32_t mCount 来做计数。RefBase中,强指针弱指针通过类型为 weakref_impl 类型的 mRefs 变量来提供计数功能,同时 weakref_impl中 也有一个RefBase * 类型的指针 mBase来指向宿主类RefBase。
其引用计数器不仅仅是简单的 接口类在RefBase中定义weakref_type:
RefBase代码片段 weakref_type 定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102//.......
//.......
// 1 RefBase 源代码
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type //接口定义
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
//! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
weakref_impl* const mRefs;
};
强指针的的定义为sp ,通过RefBase::weakref_type来实现引用计数:
RefBase.h中包含SP的头文件:
```c++
sp的定义
StrongPointer.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58// ... StrongPointer ...
//...
template <typename T>
class sp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline sp() : m_ptr(0) { }
sp(T* other);
sp(const sp<T>& other);
template<typename U> sp(U* other);
template<typename U> sp(const sp<U>& other);
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (U* other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Accessors
inline T& operator * () const { return * m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
// Optimization for wp::promote().
sp(T* p, weakref_type* refs);
T* m_ptr;
};
//...
sp的实现也在头文件中
weakref_impl 的接口在RefBase::weakref_type中定义,如上源代码。weakref_impl 继承 RefBase::weakref_type实现在
coffee@ubuntu:~/Android/system/core/libutils$ RefBase.cpp中
1 | class RefBase::weakref_impl : public RefBase::weakref_type |
RefBase.cpp 代码结构:
1 |
|
成员函数分析:1
2
3
4volatile int32_t mStrong;
volatile int32_t mWeak;
RefBase* const mBase;
volatile int32_t mFlags;
mStrong 和 mWeak 分别表示强引用计数 和弱引用计数 , mBase山文已经提到过,RefBase中,强指针弱指针通过类型为 weakref_impl 类型的 mRefs 变量来提供计数功能,同时 weakref_impl中 也有一个RefBase * 类型的指针 mBase来指向宿主类RefBase。 mFlag 表示维护 对象引用计数的 策略 取值如下:
RefBase.h1
2
3
4
5
6//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
分析sp 的实现构造函数如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
if (other) ((T*)other)->incStrong(this);
}
构造函数传入的参数T other 肯定需要继承至RefBase类
coffee@ubuntu:~/Android/system/core/libutils$
RefBase.cpp 实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43// ---------------------------------------------------------------------------
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
//增加弱引用计数
refs->incWeak(id);
//增加强引用技术
refs->addStrongRef(id);
// c 为 mStrong +1 之前的值 c == INITIAL_STRONG_VALUE 说明第一次调用
const int32_t c = android_atomic_inc(&refs->mStrong);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
// INITIAL_STRONG_VALUE : 1<<28
if (c != INITIAL_STRONG_VALUE) {
return;
}
//首次调用incStrong 函数,会调用onFirstRef函数 对象首次引用的时候需要一些逻辑处理
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
refs->mBase->onFirstRef();
}
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = android_atomic_dec(&refs->mStrong);
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
if (c == 1) {
refs->mBase->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;
}
}
refs->decWeak(id);
}