Liu Hao
Blog: Http://blog.csdn.net/liuhaoyutz
Android version: 4.4.2
In the previous article, we analyzed the strong pointer sp in the Android smart pointer, in this paper we analyze the weak pointer WP. Why do you need a weak pointer wp? Let's consider the following scenario: There are two classes in the Cparent and Cchild,cparent classes that have a smart pointer pointing to the Cchild object, and a smart pointer in the Cchild class that points to the Cparent object
Class Cparent:p ublic lightrefbase<cparent>{... Sp<cchild> SPC; ......} Class Cchild:p ublic lightrefbase<cchild>{... Sp<cparent> spp ... }
Create the Cparent class object, parent and Cchild object child, respectively, and let PARENT.SPC point to child and let CHILD.SPP point to the parent. Thus, the value of the reference counter for both parent and child is 1, and when you release parent and child, because their reference counter is 1, and the system can only deconstruct one object at a time, this creates a deadlock that cannot be used to deconstruct any of the parent and child objects. This also causes a memory leak problem. To this end, Android introduced a weak pointer WP, defined in the Frameworks/rs/cpp/util/refbase.h file, we first look at the definition of WP:
197template<typename T>198class wp199{200public:201 typedef typename REFBASE::WEAKREF_TYPEWEAKREF_TYPE;202203 inline WP (): m_ptr (0) {}204205 wp (t* other), 206 WP (const wp<t>& other); 207 WP (CONST sp<t>& Other), 208 template<typename u> wp (u* other), 209 template<typename u> wp (constsp<u>& other); 2 Ten template<typename u> wp (constwp<u>& other); 211212 ~wp (); 213214//Assignment215216 wp& operator = (t* other); 217 wp& operator = (const wp<t>&other); 218 wp& operator = (const sp<t> &other); 219220 template<typename u> wp& operator= (u* other); 221 template<typename U> wp& op erator= (const wp<u>& Other), 222 template<typename u> wp& operator= (const sp<u>& Other); 223224 void Set_object_and_refs (t* other,weakref_type* refs); 225226//promotion to sp227228 sp<t> promote ( ) const;229230//Reset231232 void Clear (); 233234//Accessors235236 inline weakref_type* get_refs () const {return m_refs;} 237238 inline t* unsafe_get () const {return m_ptr;} 239240//Operators241242 compare_weak (= =) 243 Compare_weak (! =) 244 Compare_weak (>) 245 compare_weak (<) 2 Compare_weak (<=) 247 compare_weak (>=) 248249 inline bool operator = = (constwp<t>& o) const {250 return (m_ptr = = o.m_ptr) && (m_refs = = o.m_refs); 251}252 template<typename u>253 Inline Boo L operator = = (constwp<u>& o) const {254 return m_ptr = = o.m_ptr;255}256257 inline bool operator & Gt (constwp<t>& o) const {258 return (m_ptr = = o.m_ptr)? (M_refs> o.m_refs): (M_ptr > O.m_ptr); 259}260 template<typename u>261 inline bool operator > (CO nstwp<u>& o) const {262 return (m_ptr = = o.m_ptr)? (M_refs> o.m_refs): (M_ptr > O.m_ptr); 263}264265 inline BOOL opErator < (constwp<t>& o) const {266 return (m_ptr = = o.m_ptr)? (m_refs< o.m_refs): (M_ptr < o.m_ptr); 267}268 template<typename u>269 inline bool operator < (CO nstwp<u>& o) const {return (m_ptr = = o.m_ptr)? (m_refs< o.m_refs): (M_ptr < O.M_PTR); 271}272 inline bool operator!= (const wp<t> & O) const {return m_refs! = o.m_refs;} 273 template<typename u> inline Booloperator! = (CONST wp<u>& o) Const {return!operator = = (o);} 274 inline bool operator<= (const wp<t>& o) const {return!operator > (o);} 275 template<typename u> Inline booloperator <= (const wp<u>& o) const {return!operator > (o); }276 inline bool operator>= (const wp<t>& o) Const {return!operator < (o);} 277 template<typename u> Inline booloperator >= (const wp<u>& O) Const {return!operator < (o);} 278279private:280 template<typename y> friend class sp;281 template<typename y> friend class wp;282283 t* m_ptr;284 weakref_type* m_refs;285};
As can be seen, weak pointer WP and strong pointer SP basic content is similar, but there are the following differences:
1, WP more than a weakref_type type of pointer variable m_refs.
2, WP has a promote function, used to upgrade WP to SP.
3, there is a little important difference, we will see later, WP target object's parent class is refbase instead of lightrefbase.
Android Rules:
1. When an object has a strong reference count of 0 o'clock, the object can be disposed regardless of whether the weak reference count is 0.
2, we can not directly manipulate the reference object through the weak pointer WP, if you want to operate, you must first upgrade the WP through the promote function to the SP line.
In the Frameworks/rs/cpp/util/refbase.h file, the Refbase class is defined as follows:
65class refbase 66{67public:68 void Incstrong (const void* ID) const; Decstrong (const void* ID) const; Forceincstrong void (const void* ID) const; 72 73//! Debugging Only:get Currentstrong ref count. int32_t getstrongcount () const; The Weakref_type class is public:79 refbase* refbase () const; Incweak (const void* ID); decweak void (const void* ID); Acquires a strong reference if Thereis already one. attemptincstrong bool (const VOID*ID); Acquires a weak reference if Thereis already one. A//This is not always safe. SeeProcessState.cpp and BpBinder.cpp//for the proper use. attemptincweak BOOL (const void* ID); 91 92//! Debugging Only:get current Weakref count. int32_t Getweakcount () const; 94 95//! Debugging Only:print Referencesheld on object. Printrefs () const; 97 98//! debugging only:enable tracking Forthis object. /Enable--enable/disable tracking100//Retain--whentracking is enable, if True and then we save a Stac K trace101//For each reference and dereference;when retain = = False, we102//Match up References and Dereferencesand keep only the103//outstanding ones.104105 void TR Ackme (bool Enable, Boolretain), 106};107108 weakref_type* createweak (const void* ID) const;109110 weakref_type* getweakrefs () const;111112//! Debugging Only:print references held on object.113 inline void printrefs () const {getweakrefs ()->printref S (); }114115//! debugging only:enable tracking of object.116 inline void Trackme (bool Enable, bool retain) 117 {118 getweakrefs ()->trackme (enable, retain); 119}120121 typedef refbase BASETYPE;12212 3protected:124 refbase (); ~refbase (); 126127//! Flags Forextendobjectlifetime () enum {129 Object_lifetime_strong = 0x0000,130 Object_lifetime_weak = 0x0001,131 Object_lifetime_mask = 0x0001132};133134 void Extendobjectlifetime (int32_t mode); 135136//! Flags foronincstrongattempted () 137 enum {138 First_inc_strong =0x0001139};140141 virtual void Onfirstref (); 142 virtual void Onlaststrongref (const void* ID); 143 virtual bool Onincstrongatte Mpted (uint32_tflags, const void* ID); 144 virtual void Onlastweakref (const void* ID); 145146private:147 Fri End classreferencemover;148 Static voidmovereferences (void* D, void const* S, size_t n,149 Constreferencecon verterbase& CAster) 150151private:152 Friend class weakref_type;153 class weakref_impl;154155 Refbase (CO NST refbase& o); 156 refbase& operator= (const refbase& o); 157158 weakref_impl* CONSTMR EFS;159};
Similar to the reference counter provided by Lightrefbase to the object that the SP points to, Refbase is used to provide a reference counter function to the object to which the WP points. The Lightrefbase reference counter is specifically implemented as an integer lightrefbase.mcount, but we don't have a corresponding integer in the Refbase class as the reference counter, so who is the reference counter for Refbase? It's actually a refbase.mrefs, it's a pointer to the Weakref_impl class. The Weakref_impl class has two member variables, Mstrong and Mweak, which are strong reference counts and weak reference counts. The refbase.mrefs is initialized in the Refbase constructor:
579refbase::refbase () 580 : Mrefs (Newweakref_impl (This)) 581{582}
580 line, new a Weakref_impl object, assigns a value to Refbase.mrefs.
Refbase::weakref_impl is defined in the System/core/libutils/refbase.cpp file as follows:
60class refbase::weakref_impl:public refbase::weakref_type 61{62public:63 volatile int32_t Mstrong; Volatile int32_t mweak; refbase* const mbase; int32_t volatile mflags 68#if; Debug_refs Weakref_impl (refbase* base) : Mstrong (initial_strong_value) , mweak (0) , Mbase (Base) , Mflags (0) { /*id*/}, addstrongref void (const void* remo) {} Vestrongref (const void*/*id*/) {} void Renamestrongrefid (const void*/*old_id*/, const void*/*new_id*/) {} 81
void addweakref (const void*/*id*/) {} void removeweakref (const void*/*id*/) {} void Renameweakrefid (const void*/*old_id*/, const void*/*new_id*/) {} Printrefs () const {} Trackme (bool, bool) {} 87#else ... ...... 313#endif314};
The definition of the Weakref_impl class is long, but it is used for debug debugging from 87 lines to the end, which can be ignored. The 78-85-row defined functions are not specifically implemented, so they can also be ignored.
70-76 rows, Mstrong, Mweak, Mbase, mflags are initialized in the constructor. Mstrong is initialized to Initial_strong_value, and the macro is defined in the System/core/libutils/refbase.cpp file:
56#define Initial_strong_value (1<<28)
It seems that the Weakref_impl class simply provides Mstrong, Mweak, Mbase, mflags four member variables, and initializes, without realizing what functionality, but be aware that Weakref_impl inherits from Refbase::weakref_ The type class.
As with the SP, we consider that WP point to an object (the object's weak reference count should be 1), possibly through the WP constructor, or through the overloaded "=" assignment operator. Let's look at WP's constructor, as follows:
295template<typename T>296WP<T>::WP (t* Other) 297 : M_ptr (Other) 298{299 if (other) M_refs =other- >createweak (this); 300}
Then look at the overloaded assignment operator, as follows:
350template<typename t>351wp<t>& wp<t>::operator = (t* other) 352{353 weakref_type* newRefs =354 other Other->createweak (this): 0;355 if (m_ptr) m_refs->decweak (this); 356 m_ptr = other;357 m_refs = newrefs;358 return *this;359}
Note that neither of these functions directly increases the object's weak reference count (that is, refbase.mrefs->mweak), but actually increases the weak reference count of other by calling Other->createweak (this). The function is defined in the System/core/libutils/refbase.cpp file:
568refbase::weakref_type* refbase::createweak (const void* ID) const569{570 mrefs->incweak (ID); 571 Return mrefs;572}
Line 570 calls Mrefs the Inweak function of the Weakref_impl class, adding 1 to the weak reference count.
571 rows, return refbase.mrefs, note that it is a Weakref_impl type pointer. In the WP constructor and overloaded assignment operators, the return value of the Createweak function is assigned to Wp.m_refs. This allows the reference counter Weakref_impl to be accessed through both Wp.m_refs and other.mrefs.
The function is defined as follows:
387void refbase::weakref_type::incweak (const void* ID) 388{389 weakref_impl* const IMPL =STATIC_CAST<WEAKREF_ Impl*> (this); 390 impl->addweakref (ID); 391 const int32_t C =android_atomic_inc (&impl->mweak); 392 Alog_assert (c >= 0, "Incweak called on%p after last weak ref", this); 393}
390 rows, the Addweakref function is an empty function and is not implemented.
391 lines, call Android_atomic_inc, give the weak reference count Mweak plus 1.
Analyzing here, we know how to add 1 to the weak reference count.
Then look at the destructor of WP:
344template<typename t>345wp<t>::~wp () 346{347 if (m_ptr) m_refs->decweak (this); 348}
It calls M_refs, the Weakref_type.decweak function, which is defined as follows:
396void Refbase::weakref_type::d ecweak (const void* ID) 397{398 weakref_impl* const IMPL =static_cast<weakref_impl*& gt; (this); 399 Impl->removeweakref (ID); n-Const int32_t C =android_atomic_dec (&impl->mweak); 401 Alog_as SERT (c >= 1, "Decweak called on%p Too many times", this); 402 if (c! = 1) return;403404 if ((Impl->mflags&ob Ject_lifetime_weak) = = Object_lifetime_strong) {405//This was the Regularlifetime case. The object is destroyed406//At the last strongreference goes away. Since weakref_impl407//outlive the Object,it is not destroyed in the dtor, and408//We'll have to do ithe re.409 if (Impl->mstrong ==initial_strong_value) {410//special Case:wenever had a strong reference , so we need to411//Destroy Theobject now.412 deleteimpl->mbase;413} else {414 ALOGV ("Freeingrefs%p of Old Refbase%p\n", this, impl->mbase); 415 Delete impl;416}417} else {418//Less common case:lifetime is object_lifetime_{weak| forever}419 impl->mbase->onlastweakref (ID); 420 if (impl->mflags&object_lifetime_mask) = = OBJECT_ Lifetime_weak) {421//This was theobject_lifetime_weak case. The last weak-reference422//Is gone, we candestroy the object.423 deleteimpl->mbase;424 }425}426}
400 lines, call Android_atomic_dec to reduce the weak reference count.
402 rows, if the weak reference count is not 0, exit directly.
404-425 lines, according to whether it is a strong reference, respectively, the release work.
What happens if you use an SP pointer to point to a class object that inherits Refbase? From the previous article analyzing the SP, we know that the Refbase.incstrong function is called at this point, which is defined as follows:
318void Refbase::incstrong (const void* ID) const319{320 weakref_impl* const refs =mrefs;321 Refs->incweak ( ID); 322323 refs->addstrongref (ID); 324 const int32_t C =android_atomic_inc (&refs->mstrong); 325 Alog_assert (C > 0, "Incstrong () called on%p after last strong ref", refs); 326#if print_refs327 ALOGD ("Incstrong of%pfrom%p:cnt=%d\n", this, ID, c); 328#endif329 if (c!=initial_strong_value) { return;331 }332333 android_atomic_add (-initial_strong_value, &refs->mstrong); 334 refs-> Mbase->onfirstref (); 335}
320 lines, Mrefs is the corresponding counter of the refbase.
321 rows, increasing the weak reference count.
323 lines, Addstrongref is an empty function.
324 lines, call Android_atomic_inc to increase the reference count, that is, Weakref_impl.mstrong.
329-331 rows, if not the first time a strong pointer reference, directly returned.
333 lines, if it is the first time a strong pointer reference, the value of Mstrong also need to subtract initial_strong_value, its value is 1.
334 lines, Refs->mbase->onfirstref () is an empty function.
When a strong reference is released, the Decstrong function is called:
337void refbase::d ecstrong (const void* ID) const338{339 weakref_impl* const refs =mrefs;340 refs-> Removestrongref (ID); 341 const int32_t C =android_atomic_dec (&refs->mstrong); 342#if print_refs343 ALOGD ("Decstrong of%pfrom%p:cnt=%d\n", this, ID, c); 344#endif345 Alog_assert (c >= 1, "Decstrong () called-%p to o many times ", refs); 346 if (c = = 1) {347 refs->mbase->onlaststrongref (ID); 348 if (refs->mflags &object_lifetime_mask) = = Object_lifetime_strong) {349 delete this;350 }351 }352 refs-> Decweak (ID); 353}
339 lines, Mrefs is the corresponding counter of the refbase.
340 rows, the Removestrongref function is an empty function.
341 lines, the strong reference count Mstrong minus 1.
346 lines, when the strong reference is all freed, the object is disposed.
352 lines, call the Decweak function to subtract 1 from the weak reference count.