android分析之智能指针
- 智能指针是一个包装类,该类有一个指针指向真正的类对象
- 引用计数型智能指针,该引用计数是在应该被真正类所持有,而非包装类(智能指针)
- 为了方便,会将引用计数单独实现在一个类中,这样所有继承它的类都有计数器
// --------------------------------------------------------------------------- template <typename T> class sp { public: 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); 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; void set_pointer(T* ptr); T* m_ptr;//指向真正的类对象的指针 };
// --------------------------------------------------------------------------- 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; 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 }; 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 ReferenceMover; static void moveReferences(void* d, void const* s, size_t n, const ReferenceConverterBase& caster); private: friend class weakref_type; class weakref_impl; RefBase(const RefBase& o); RefBase& operator=(const RefBase& o); weakref_impl* const mRefs; };
// --------------------------------------------------------------------------- class RefBase::weakref_impl : public RefBase::weakref_type//引用计数器的实现类 { public: volatile int32_t mStrong;//强引用 volatile int32_t mWeak;//若引用 RefBase* const mBase; volatile int32_t mFlags; #if !DEBUG_REFS 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; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Strong references remain!"); #else ALOGE("Strong references remain:"); #endif 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 refs->stack.dump(); #endif refs = refs->next; } } if (!mRetain && mWeakRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Weak references remain:"); #else ALOGE("Weak references remain!"); #endif 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 refs->stack.dump(); #endif refs = refs->next; } } if (dumpStack) { ALOGE("above errors at:"); CallStack stack; stack.update(); stack.dump(); } } void addStrongRef(const void* id) { //ALOGD_IF(mTrackEnabled, // "addStrongRef: RefBase=%p, id=%p", mBase, id); addRef(&mStrongRefs, id, mStrong); } 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); } } 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); } void removeWeakRef(const void* id) { if (!mRetain) { removeRef(&mWeakRefs, id); } else { addRef(&mWeakRefs, id, -mWeak); } } 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]; sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); text.append(buf); printRefsLocked(&text, mStrongRefs); sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this); text.append(buf); printRefsLocked(&text, mWeakRefs); } { char name[100]; snprintf(name, 100, "/data/%p.stack", this); int rc = open(name, O_RDWR | O_CREAT | O_APPEND); if (rc >= 0) { 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 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.update(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; } #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p" "(weakref_type %p) that doesn't exist!", id, mBase, this); #endif 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 stack; stack.update(); stack.dump(); } } 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 ? '+' : '-'; sprintf(buf, "\t%c ID %p (ref %d):\n", inc, refs->id, refs->ref); out->append(buf); #if DEBUG_REFS_CALLSTACK_ENABLED out->append(refs->stack.toString("\t\t")); #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 };
小结:
- 通常情况下,智能指针分为sp和wp
- 目标对象的父类是RefBase——这个基类提供了一个weakref_impl类型的引用计数器,可以同时进行强弱引用的控制