首页 > 代码库 > android分析之智能指针

android分析之智能指针

  1. 智能指针是一个包装类,该类有一个指针指向真正的类对象
  2. 引用计数型智能指针,该引用计数是在应该被真正类所持有,而非包装类(智能指针)
  3. 为了方便,会将引用计数单独实现在一个类中,这样所有继承它的类都有计数器
// ---------------------------------------------------------------------------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};

  

  小结:

  1. 通常情况下,智能指针分为sp和wp
  2. 目标对象的父类是RefBase——这个基类提供了一个weakref_impl类型的引用计数器,可以同时进行强弱引用的控制

 

android分析之智能指针