- A smart pointer is a wrapper class that has a pointer to a real class object
- Reference count smart pointer, which is the reference count that should be held by the real class, not the wrapper class (smart pointer)
- For convenience, the reference count is implemented separately in a class so that all classes that inherit it have counters
---------------------------------------------------------------------------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;} Override operator to get the real object 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;//Pointer to a real class object};
---------------------------------------------------------------------------class refbase//All classes that inherit the class hold a counter { 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//This corresponds to the counter {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 = 0x000 1, 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);p Rivate:friend class Referencemover; static void Movereferences (void* D, void const* S, size_t N, const referenceconverterbase& caster);p rivate: 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//Reference counter Implementation class {Public:volatile int32_t mstrong;//Strong reference volatile int32_t mweak;//if reference Refbas e* 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_st Rong_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 L Og_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->sta Ck.dump (); #endif refs = refs->next; }} if (!mretain && mweakrefs! = NULL) {DumpStack = true; #if Debug_refs_fatal_sanity_che CKS 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->sta Ck.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, +, "/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 (mmute x); 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 th e address ones. bool Mretain; #endif};
Summary:
- Typically, smart pointers are divided into SP and WP
- The parent class of the target object is refbase--this base class provides a reference counter for the Weakref_impl type that can be controlled at the same time as the strength reference
Smart pointers for Android Analytics