「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。
简述
Android的智能指针,主要是为了在详细阅读了一些博客后加深对于智能指针的影响,而写的一篇总结性,或者说自我理解(分析)性的一篇文章。 智能指针,是为了更方便地管理对象的生命周期而存在的。
详解
轻量级指针
实现原理分析
轻量级指针在Android系统中的类为LigheRefBase类,其定义在
system/core/include/utils/LightRefBase.h
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,三个成员方法,incStrong方法,decStrong方法,getStrongCount方法,其中 1. 成员变量mCount的类型为int32_t,其初始化为0,它的作用是记录当前模板类引用的次数 2. 成员方法incStrong和decStrong用作操作mCount完成模板类引用次数的变化 3. 成员方法getStrongCount完成获取模板类引用次数 4. 观察成员方法decStrong方法,其在减少成员变量mCount的同时,会检查若mCount为0的情况下,直接delete该对象,从而达到资源回收
与轻量级指针的引用计数器相互配合的智能指针类为sp,它位于
/system/core/include/utils/StrongPointer.h
template<typename T>
class sp {
public:
inline sp() : m_ptr(nullptr) { }
sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (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; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
对于轻量级指针来说,sp类我们需要关注的有 1. 成员变量m_ptr,它指向的是模板类 2. 确认sp的构造函数
template<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);
}
可以看到,这两个构造函数中,均先初始化m_ptr,我们知道,T总是会继承LightRefBase类的,因此m_ptr的incStrong方法,即是调用LightRefBase类的incStrong方法,因此会直接增加LightRefBase的成员变量mCount的值 3. sp的析构函数
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
析构函数中,主要是确认m_ptr不为NULL的情况下,调用其decStrong方法,即调用LightRefBase类的devStrong方法,从而减少模板类LightRefBase类的成员变量mCount,并且确认如果mCount为0时,回收模板类对象,从而释放资源
强指针和弱指针
RefBase基类
定义
在介绍强指针和弱指针之前,我们有必要先分析一下RefBase类,此类是强指针和弱指针的基类,位于
/system/core/include/utils/RefBase.h
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);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
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);
}
typedef RefBase basetype;
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
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
private:
friend class ReferenceMover;
static void renameRefs(size_t n, const ReferenceRenamer& renamer);
static void renameRefId(weakref_type* ref, const void* old_id,
const void* new_id);
static void renameRefId(RefBase* ref, const void* old_id,
const void* new_id);
weakref_impl* const mRefs;
};
从上述基类定义中可以看到 1. RefBase中定义有一个类weakref_type 2. 包含有一个成员变量,类型为weakref_impl地址的mRefs,而weakref_impl的定义在
/system/core/libutils/RefBase.cpp
class RefBase::weakref_impl: public RefBase::weakref_type {
public:
std::atomic<int32_t> mStrong;
std::atomic<int32_t> mWeak;
RefBase* const mBase;
std::atomic<int32_t> mFlags;
#if !DEBUG_REFS
explicit weakref_impl(RefBase* base) :
mStrong(INITIAL_STRONG_VALUE), mWeak(0), mBase(base), mFlags(0) {
}
void addStrongRef(const void* /*id*/) {}
void removeStrongRef(const void* /*id*/) {}
void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) {}
void addWeakRef(const void* /*id*/) {}
void removeWeakRef(const void* /*id*/) {}
void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) {}
void printRefs() const {}
void trackMe(bool, bool) {}
#else
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)
{}
~weakref_impl()
{
bool dumpStack = false;
if (!mRetain && mStrongRefs != NULL) {
dumpStack = true;
ALOGE("Strong references remain:");
ref_entry* refs = mStrongRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG, refs->stack.get());
#endif
refs = refs->next;
}
}
if (!mRetain && mWeakRefs != NULL) {
dumpStack = true;
ALOGE("Weak references remain!");
ref_entry* refs = mWeakRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG, refs->stack.get());
#endif
refs = refs->next;
}
}
if (dumpStack) {
ALOGE("above errors at:");
CallStack::logStack(LOG_TAG);
}
}
void addStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "addStrongRef: RefBase=%p, id=%p", mBase, id);
addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed));
}
void removeStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "removeStrongRef: RefBase=%p, id=%p", mBase, id);
if (!mRetain) {
removeRef(&mStrongRefs, id);
} else {
addRef(&mStrongRefs, id, -mStrong.load(std::memory_order_relaxed));
}
}
void renameStrongRefId(const void* old_id, const void* new_id) {
//ALOGD_IF(mTrackEnabled,
// "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
// mBase, old_id, new_id);
renameRefsId(mStrongRefs, old_id, new_id);
}
void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
}
void removeWeakRef(const void* id) {
if (!mRetain) {
removeRef(&mWeakRefs, id);
} else {
addRef(&mWeakRefs, id, -mWeak.load(std::memory_order_relaxed));
}
}
void renameWeakRefId(const void* old_id, const void* new_id) {
renameRefsId(mWeakRefs, old_id, new_id);
}
void trackMe(bool track, bool retain)
{
mTrackEnabled = track;
mRetain = retain;
}
void printRefs() const
{
String8 text;
{
Mutex::Autolock _l(mMutex);
char buf[128];
snprintf(buf, sizeof(buf),
"Strong references on RefBase %p (weakref_type %p):\n",
mBase, this);
text.append(buf);
printRefsLocked(&text, mStrongRefs);
snprintf(buf, sizeof(buf),
"Weak references on RefBase %p (weakref_type %p):\n",
mBase, this);
text.append(buf);
printRefsLocked(&text, mWeakRefs);
}
{
char name[100];
snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
this);
int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
if (rc >= 0) {
(void)write(rc, text.string(), text.length());
close(rc);
ALOGD("STACK TRACE for %p saved in %s", this, name);
}
else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
name, strerror(errno));
}
}
private:
struct ref_entry
{
ref_entry* next;
const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack::CallStackUPtr stack;
#endif
int32_t ref;
};
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 = CallStack::getCurrent(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
void removeRef(ref_entry** refs, const void* id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* const head = *refs;
ref_entry* ref = head;
while (ref != NULL) {
if (ref->id == id) {
*refs = ref->next;
delete ref;
return;
}
refs = &ref->next;
ref = *refs;
}
ALOGE("RefBase: removing id %p on RefBase %p"
"(weakref_type %p) that doesn't exist!",
id, mBase, this);
ref = head;
while (ref) {
char inc = ref->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
ref = ref->next;
}
CallStack::logStack(LOG_TAG);
}
}
void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = r;
while (ref != NULL) {
if (ref->id == old_id) {
ref->id = new_id;
}
ref = ref->next;
}
}
}
void printRefsLocked(String8* out, const ref_entry* refs) const
{
char buf[128];
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
inc, refs->id, refs->ref);
out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
out->append(CallStack::stackToString("\t\t", refs->stack.get()));
#else
out->append("\t\t(call stacks disabled)");
#endif
refs = refs->next;
}
}
mutable Mutex mMutex;
ref_entry* mStrongRefs;
ref_entry* mWeakRefs;
bool mTrackEnabled;
// Collect stack traces on addref and removeref, instead of deleting the stack references
// on removeref that match the address ones.
bool mRetain;
#endif
};
可以看到,这个类继承了RefBase.h中定义的weakref_type类,而且这段代码看上去非常复杂,但是如果分析发现
#if !DEBUG_REFS
// Release版本走到的分支
……
#else
// Debug版本走到的分支
……
#endif
而且从Release部分可以看到,所有定义的函数均为空实现,仅在构造函数中做了一些初始化操作 (由于Debug调试版本,我们一般不需要使用,因此此处也不再分析) 3. 注意到RefBase的定义中,包含了一个枚举类型
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
OBJECT_LIFETIME_STRONG 表示对象的生命周期只受强引用计数影响
OBJECT_LIFETIME_WEAK表示对象的生命周期只受弱引用计数影响
OBJECT_LIFETIME_MASK是一个标杆
构造方法和析构方法
RefBase的构造方法
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{}
初始化了mRefs
析构函数
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) {
……
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = nullptr;
}
首先获取Flags,确认 如果对象的生命周期受到弱引用计数影响,则当弱引用为0时(由于强引用计数必定会小于或者等于弱引用计数),强引用计数必定为0,则释放weakref_impl所占用的内存 如果对象的生命周期不受到弱引用计数的影响(即收到强引用计数影响),判断强引用计数为初始化值,则不做任何操作 最后强制设置mRefs为nullptr。
强指针的实现原理分析
强指针的智能指针类也是sp,它位于
/system/core/include/utils/StrongPointer.h
template<typename T>
class sp {
public:
inline sp() : m_ptr(nullptr) { }
sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (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; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
前面已经说过,这是一个模板类。 它的构造函数如下:
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
由于这个m_ptr现在已经是RefBase类,因此其调用的是RefBase类的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);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#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 __unused = 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);
refs->mBase->onFirstRef();
}
从这边看 首先先通过调用incWeak方法,增加弱引用计数 之后调用addStrongRef方法,在此前分析过,在Release版本中,此方法不做任何操作 紧接着增加对象的强引用计数,然后判断是否为第一次进入构造函数,若是第一次,则调用对象的onFirstRef方法,若不是第一次,直接返回 综上:incStrong函数中主要是增加了强引用计数和弱引用计数,并且在第一次调用的时候,同时调用对象的onFirstRef方法 析构函数主要做了:
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
同样,在此前分析过,此方法调用了RefBase类的decStrong方法
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);
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.
//
// Since we're doing atomic loads of `flags`, the static analyzer assumes
// they can change between `delete this;` and `refs->decWeak(id);`. This is
// not the case. The analyzer may become more okay with this patten when
// https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
refs->decWeak(id);
}
主要是做了
- 首先调用了weakref_impl的removeStrongRef方法,通过此前分析,在Release版本中,此方法不做任何操作
- 调用atomic的fetch_sub方法,强引用指针计数减1
- 当强指针计数正好是1的时候,当flags为受到强指针引用计数影响的时候,直接释放此对象,即调用RefBase的析构函数
- 而经过上述分析,RefBase的析构函数中判断弱指针计数是否为1,若为1的话,直接释放mRefs对象内存
- 此后,弱引用计数减少1
综上,sp的析构函数主要是调用了RefBase的decStrong方法,用作强指针计数减少1,之后当强指针减少1后,为0,且对象收到强指针引用计数影响的时候,释放对象,此后弱引用计数减少1
弱指针的实现原理分析
弱指针的类为wp,位于
/system/core/include/utils/RefBase.h
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(nullptr) { }
wp(T* other); // NOLINT(implicit)
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(U* other); // NOLINT(implicit)
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
// Assignment
wp& operator = (T* other);
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (U* other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK(>)
COMPARE_WEAK(<)
COMPARE_WEAK(<=)
COMPARE_WEAK(>=)
inline bool operator == (const wp<T>& o) const {
return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
}
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_ptr == o.m_ptr;
}
inline bool operator > (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
inline bool operator < (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr;
weakref_type* m_refs;
};
从上述类定义来看,弱指针引用类wp同样是一个模板类。 构造函数
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
此函数调用了模板T类的createWeak方法,而T肯定是继承自RefBase类的,也就是说,会调用RefBase类的createWeak方法
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
原来只是增加了弱引用计数,并且返回的是RefBase的weakref_impl对象mRefs
析构函数
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
恩,调用了mRefs的decWeak函数,用作减少弱引用计数
弱指针升级强指针引用
弱指针不能直接操作所引用的对象,因此,如果需要操作引用的对象,则必须要将弱引用指针升级为强引用指针,因此弱引用模板类wp就提供了promote方法,来操作弱引用计数升级为强引用计数
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;
}
m_ptr为对象的实际类型,其在构造函数中初始化,然后m_refs为weakref_impl对象,在构造函数中初始化返回为RefBase的mRefs对象,因此
bool RefBase::weakref_type::attemptIncStrong(const void* id) {
incWeak(id);
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
this);
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 <= 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
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
if ((flags & OBJECT_LIFETIME_MASK) == 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 (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 (e.g.: another thread has inc/decStrong'ed us)
// curCount has been updated.
}
if (curCount <= 0) {
// promote() failed, some other thread destroyed us in the
// meantime (i.e.: strong count reached zero).
decWeak(id);
return false;
}
} else {
// this object has an "extended" life-time, i.e.: it can be
// revived from a weak-reference only.
// Ask the object's implementation if it agrees to be revived
if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
// it didn't so give-up.
decWeak(id);
return false;
}
// grab a strong-reference, which is always safe due to the
// extended life-time.
curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
// If the strong reference count has already been incremented by
// someone else, the implementor of onIncStrongAttempted() is holding
// an unneeded reference. So call onLastStrongRef() here to remove it.
// (No, this is not pretty.) Note that we MUST NOT do this if we
// are in fact acquiring the first reference.
if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
impl->mBase->onLastStrongRef(id);
}
}
}
impl->addStrongRef(id);
// curCount is the value of mStrong before we incremented it.
// 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 > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
// this in the middle of another incStrong. The subtraction is handled
// by the thread that started with INITIAL_STRONG_VALUE.
if (curCount == INITIAL_STRONG_VALUE) {
impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
}
return true;
}
- 首先,将this指针转化为weakref_impl指针,并且保存在impl中
- 接下来,获取mStrong的值,存储在curCount中
- 判断当前的强指针计数是否大于0,而且不等于INITIAL_STRONG_VALUE,这就表示有其他对象正在使用这个强引用指针,则给强引用计数增加1,按照这一种情况,则下面的if语句会不成立,直接跳过if语句,此后会直接调用addStrongRef方法,而根据之前的分析,这个方法在Release版本中,无任何操作。
- 若上述第三条中所述if语句成立,则就是另一种情况,即上述对象从来没有被强引用计数引用,那么会进入if语句。
这个会有两种情况,
- 当对象的生命周期只受强引用影响的情况,当强引用计数小于等于0时,即强引用计数已经被摧毁,则无法将弱引用指针升级为强指针,返回false;当curCount大于0时,也就是说curCount为INITIAL_STRONG_VALUE,这种情况需要将强引用指针增加1,也就表明,可以将弱引用指针升级为强引用指针,然后判断其是否为其他线程操作销毁,若销毁,则升级失败,反之升级成功;
- 当对象的生命周期不受强引用影响,则表明可以直接升级,将强引用指针计数加1 接下来,如果成功将强引用指针计数加1,也就是说,弱引用指针升级为强引用指针成功,则调用set_pointer方法
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
即直接赋值操作 返回该模板参数的实际类型对应的对象 到此,弱引用指针计数升级为强引用指针计数就介绍完了
应用实例分析
扩展
C++中的explicit
explicit是C++中的关键字,它只能用来修饰只有一个参数的构造函数,表示显示构造函数,它和implicit是一对关键字,implicit表示隐式构造函数
C++中的atomic(fence_add、fence_sub、load、store、compare_exchange_weak)
fence_add方法
原型
T fetch_add (T val, memory_order sync = memory_order_seq_cst) volatile
----参数T为整型
T fetch_add (ptrdiff_t val, memory_order sync = memory_order_seq_cst) volatile
----参数val为指针
含义
C++ 11标准库的原子类型,主要是将原子对象的封装值加 val,并返回原子对象的旧值,整个过程是原子的。
参数
val
----两个构造函数中,第一个构造函数表示原子类型的模板参数,第二个构造函数表示指针类型
sync
----原子操作的同步模式,是枚举类型memory_order类型值,若不指定的话,默认为memory_order_seq_cst
返回值
对应原子对象的模板类型
fence_sub方法
原型
T fetch_sub (T val, memory_order sync = memory_order_seq_cst) volatile
----参数T为整型
T fetch_sub (ptrdiff_t val, memory_order sync = memory_order_seq_cst) volatile
----参数val为指针
含义
C++ 11标准库的原子类型,主要是将原子对象的封装值减 val,并返回原子对象的旧值,整个过程是原子的
参数
val
----两个构造函数中,第一个构造函数表示原子类型的模板参数,第二个构造函数表示指针类型
sync
----原子操作的同步模式,是枚举类型memory_order类型值,若不指定的话,默认为memory_order_seq_cst
返回值
对应原子对象的模板类型
load方法
原型
T load (memory_order sync = memory_order_seq_cst) const volatile;
含义
加载对应原子对象的值
参数
sync
----原子操作的同步模式,是枚举类型memory_order类型值,若不指定的话,默认为memory_order_seq_cst
返回值
对应原子对象的模板类型
store方法
原型
void store (T val, memory_order sync = memory_order_seq_cst) volatile
含义
存储对应的原子对象的模板类型val到原子对象中
参数
sync
----原子操作的同步模式,是枚举类型memory_order类型值,若不指定的话,默认为memory_order_seq_cst
返回值(void)
compare_exchange_weak方法和compare_exchange_strong方法
原型
bool compare_exchange_weak (T& expected, T val, memory_order sync = memory_order_seq_cst) volatile;
bool compare_exchange_weak (T& expected, T val, memory_order success, memory_order failure) volatile;
bool compare_exchange_strong (T& expected, T val, memory_order sync = memory_order_seq_cst) volatile;
bool compare_exchange_strong (T& expected, T val, memory_order success, memory_order failure) volatile;
含义
比较对象数值与expected值进行比较
两个memory_order的方法的含义是,当上述结果为true的时候,使用success的memory_order,反之使用failure
weak形式允许假失败,该函数直接比较原子对象所封装的值与参数 expected 的物理内容,所以某些情况下,对象的比较操作在使用 operator==() 判断时相等,但 compare_exchange_weak 判断时却可能失败,因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3,它们在逻辑上都表示"真",但在物理上两者的表示并不相同)。可以虚假的返回false(和expected相同)。若本atomic的T值和expected相同则用val值替换本atomic的T值,返回true;若不同则用本atomic的T值替换expected,返回false。
与compare_exchange_weak 不同, strong版本的 compare-and-exchange 操作不允许(spuriously 地)返回 false,即原子对象所封装的值与参数 expected 的物理内容相同,比较操作一定会为 true。不过在某些平台下,如果算法本身需要循环操作来做检查, compare_exchange_weak 的性能会更好。因此对于某些不需要采用循环操作的算法而言, 通常采用compare_exchange_strong 更好
参数
T表示原子对象的模板类型,其他如上述含义描述
返回值
若比较得到true,则将val的值替换对象数值
若比较得到false,将对象数值替换到expected中
枚举类型memory_order的值及含义
memory_order的定义
typedef enum memory_order {
memory_order_relaxed, // relaxed
memory_order_consume, // consume
memory_order_acquire, // acquire
memory_order_release, // release
memory_order_acq_rel, // acquire/release
memory_order_seq_cst // sequentially consistent
} memory_order;
各枚举值所对应的含义
memory_order_relaxed 表示在操作原子类型的时,同一个线程中的原子操作是有序的,而不同线程中,是不能确保顺序的
memory_order_consume, memory_order_acquire和memory_order_release 这两个值是一对值,遵循release-acquire的顺序
memory_order_acq_rel
memory_order_seq_cst
表示在操作原子类型时,严格按照程序的运行顺序顺序操作,同一时间,只有一个原子操作。牺牲优化效率,确保指令顺序一致性,如对于store和load方法来说,首先需要确认每个线程内部,各自顺序操作,然后确保在不同线程中,load方法在store方法调用后操作