Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2005 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_REF_BASE_H
     18 #define ANDROID_REF_BASE_H
     19 
     20 #include <cutils/atomic.h>
     21 #include <utils/TextOutput.h>
     22 
     23 #include <stdint.h>
     24 #include <sys/types.h>
     25 #include <stdlib.h>
     26 
     27 // ---------------------------------------------------------------------------
     28 namespace android {
     29 
     30 template<typename T> class wp;
     31 
     32 // ---------------------------------------------------------------------------
     33 
     34 #define COMPARE_WEAK(_op_)                                      \
     35 inline bool operator _op_ (const sp<T>& o) const {              \
     36     return m_ptr _op_ o.m_ptr;                                  \
     37 }                                                               \
     38 inline bool operator _op_ (const T* o) const {                  \
     39     return m_ptr _op_ o;                                        \
     40 }                                                               \
     41 template<typename U>                                            \
     42 inline bool operator _op_ (const sp<U>& o) const {              \
     43     return m_ptr _op_ o.m_ptr;                                  \
     44 }                                                               \
     45 template<typename U>                                            \
     46 inline bool operator _op_ (const U* o) const {                  \
     47     return m_ptr _op_ o;                                        \
     48 }
     49 
     50 #define COMPARE(_op_)                                           \
     51 COMPARE_WEAK(_op_)                                              \
     52 inline bool operator _op_ (const wp<T>& o) const {              \
     53     return m_ptr _op_ o.m_ptr;                                  \
     54 }                                                               \
     55 template<typename U>                                            \
     56 inline bool operator _op_ (const wp<U>& o) const {              \
     57     return m_ptr _op_ o.m_ptr;                                  \
     58 }
     59 
     60 // ---------------------------------------------------------------------------
     61 
     62 class RefBase
     63 {
     64 public:
     65             void            incStrong(const void* id) const;
     66             void            decStrong(const void* id) const;
     67 
     68             void            forceIncStrong(const void* id) const;
     69 
     70             //! DEBUGGING ONLY: Get current strong ref count.
     71             int32_t         getStrongCount() const;
     72 
     73     class weakref_type
     74     {
     75     public:
     76         RefBase*            refBase() const;
     77 
     78         void                incWeak(const void* id);
     79         void                decWeak(const void* id);
     80 
     81         bool                attemptIncStrong(const void* id);
     82 
     83         //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
     84         bool                attemptIncWeak(const void* id);
     85 
     86         //! DEBUGGING ONLY: Get current weak ref count.
     87         int32_t             getWeakCount() const;
     88 
     89         //! DEBUGGING ONLY: Print references held on object.
     90         void                printRefs() const;
     91 
     92         //! DEBUGGING ONLY: Enable tracking for this object.
     93         // enable -- enable/disable tracking
     94         // retain -- when tracking is enable, if true, then we save a stack trace
     95         //           for each reference and dereference; when retain == false, we
     96         //           match up references and dereferences and keep only the
     97         //           outstanding ones.
     98 
     99         void                trackMe(bool enable, bool retain);
    100     };
    101 
    102             weakref_type*   createWeak(const void* id) const;
    103 
    104             weakref_type*   getWeakRefs() const;
    105 
    106             //! DEBUGGING ONLY: Print references held on object.
    107     inline  void            printRefs() const { getWeakRefs()->printRefs(); }
    108 
    109             //! DEBUGGING ONLY: Enable tracking of object.
    110     inline  void            trackMe(bool enable, bool retain)
    111     {
    112         getWeakRefs()->trackMe(enable, retain);
    113     }
    114 
    115     // used to override the RefBase destruction.
    116     class Destroyer {
    117         friend class RefBase;
    118     public:
    119         virtual ~Destroyer();
    120     private:
    121         virtual void destroy(RefBase const* base) = 0;
    122     };
    123 
    124     // Make sure to never acquire a strong reference from this function. The
    125     // same restrictions than for destructors apply.
    126     void setDestroyer(Destroyer* destroyer);
    127 
    128 protected:
    129                             RefBase();
    130     virtual                 ~RefBase();
    131 
    132     //! Flags for extendObjectLifetime()
    133     enum {
    134         OBJECT_LIFETIME_WEAK    = 0x0001,
    135         OBJECT_LIFETIME_FOREVER = 0x0003
    136     };
    137 
    138             void            extendObjectLifetime(int32_t mode);
    139 
    140     //! Flags for onIncStrongAttempted()
    141     enum {
    142         FIRST_INC_STRONG = 0x0001
    143     };
    144 
    145     virtual void            onFirstRef();
    146     virtual void            onLastStrongRef(const void* id);
    147     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    148     virtual void            onLastWeakRef(const void* id);
    149 
    150 private:
    151     friend class weakref_type;
    152     class weakref_impl;
    153 
    154                             RefBase(const RefBase& o);
    155             RefBase&        operator=(const RefBase& o);
    156 
    157         weakref_impl* const mRefs;
    158 };
    159 
    160 // ---------------------------------------------------------------------------
    161 
    162 template <class T>
    163 class LightRefBase
    164 {
    165 public:
    166     inline LightRefBase() : mCount(0) { }
    167     inline void incStrong(const void* id) const {
    168         android_atomic_inc(&mCount);
    169     }
    170     inline void decStrong(const void* id) const {
    171         if (android_atomic_dec(&mCount) == 1) {
    172             delete static_cast<const T*>(this);
    173         }
    174     }
    175     //! DEBUGGING ONLY: Get current strong ref count.
    176     inline int32_t getStrongCount() const {
    177         return mCount;
    178     }
    179 
    180 protected:
    181     inline ~LightRefBase() { }
    182 
    183 private:
    184     mutable volatile int32_t mCount;
    185 };
    186 
    187 // ---------------------------------------------------------------------------
    188 
    189 template <typename T>
    190 class sp
    191 {
    192 public:
    193     typedef typename RefBase::weakref_type weakref_type;
    194 
    195     inline sp() : m_ptr(0) { }
    196 
    197     sp(T* other);
    198     sp(const sp<T>& other);
    199     template<typename U> sp(U* other);
    200     template<typename U> sp(const sp<U>& other);
    201 
    202     ~sp();
    203 
    204     // Assignment
    205 
    206     sp& operator = (T* other);
    207     sp& operator = (const sp<T>& other);
    208 
    209     template<typename U> sp& operator = (const sp<U>& other);
    210     template<typename U> sp& operator = (U* other);
    211 
    212     //! Special optimization for use by ProcessState (and nobody else).
    213     void force_set(T* other);
    214 
    215     // Reset
    216 
    217     void clear();
    218 
    219     // Accessors
    220 
    221     inline  T&      operator* () const  { return *m_ptr; }
    222     inline  T*      operator-> () const { return m_ptr;  }
    223     inline  T*      get() const         { return m_ptr; }
    224 
    225     // Operators
    226 
    227     COMPARE(==)
    228     COMPARE(!=)
    229     COMPARE(>)
    230     COMPARE(<)
    231     COMPARE(<=)
    232     COMPARE(>=)
    233 
    234 private:
    235     template<typename Y> friend class sp;
    236     template<typename Y> friend class wp;
    237 
    238     // Optimization for wp::promote().
    239     sp(T* p, weakref_type* refs);
    240 
    241     T*              m_ptr;
    242 };
    243 
    244 template <typename T>
    245 TextOutput& operator<<(TextOutput& to, const sp<T>& val);
    246 
    247 // ---------------------------------------------------------------------------
    248 
    249 template <typename T>
    250 class wp
    251 {
    252 public:
    253     typedef typename RefBase::weakref_type weakref_type;
    254 
    255     inline wp() : m_ptr(0) { }
    256 
    257     wp(T* other);
    258     wp(const wp<T>& other);
    259     wp(const sp<T>& other);
    260     template<typename U> wp(U* other);
    261     template<typename U> wp(const sp<U>& other);
    262     template<typename U> wp(const wp<U>& other);
    263 
    264     ~wp();
    265 
    266     // Assignment
    267 
    268     wp& operator = (T* other);
    269     wp& operator = (const wp<T>& other);
    270     wp& operator = (const sp<T>& other);
    271 
    272     template<typename U> wp& operator = (U* other);
    273     template<typename U> wp& operator = (const wp<U>& other);
    274     template<typename U> wp& operator = (const sp<U>& other);
    275 
    276     void set_object_and_refs(T* other, weakref_type* refs);
    277 
    278     // promotion to sp
    279 
    280     sp<T> promote() const;
    281 
    282     // Reset
    283 
    284     void clear();
    285 
    286     // Accessors
    287 
    288     inline  weakref_type* get_refs() const { return m_refs; }
    289 
    290     inline  T* unsafe_get() const { return m_ptr; }
    291 
    292     // Operators
    293 
    294     COMPARE_WEAK(==)
    295     COMPARE_WEAK(!=)
    296     COMPARE_WEAK(>)
    297     COMPARE_WEAK(<)
    298     COMPARE_WEAK(<=)
    299     COMPARE_WEAK(>=)
    300 
    301     inline bool operator == (const wp<T>& o) const {
    302         return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
    303     }
    304     template<typename U>
    305     inline bool operator == (const wp<U>& o) const {
    306         return m_ptr == o.m_ptr;
    307     }
    308 
    309     inline bool operator > (const wp<T>& o) const {
    310         return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    311     }
    312     template<typename U>
    313     inline bool operator > (const wp<U>& o) const {
    314         return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    315     }
    316 
    317     inline bool operator < (const wp<T>& o) const {
    318         return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    319     }
    320     template<typename U>
    321     inline bool operator < (const wp<U>& o) const {
    322         return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    323     }
    324                          inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
    325     template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
    326                          inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
    327     template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
    328                          inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
    329     template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
    330 
    331 private:
    332     template<typename Y> friend class sp;
    333     template<typename Y> friend class wp;
    334 
    335     T*              m_ptr;
    336     weakref_type*   m_refs;
    337 };
    338 
    339 template <typename T>
    340 TextOutput& operator<<(TextOutput& to, const wp<T>& val);
    341 
    342 #undef COMPARE
    343 #undef COMPARE_WEAK
    344 
    345 // ---------------------------------------------------------------------------
    346 // No user serviceable parts below here.
    347 
    348 template<typename T>
    349 sp<T>::sp(T* other)
    350     : m_ptr(other)
    351 {
    352     if (other) other->incStrong(this);
    353 }
    354 
    355 template<typename T>
    356 sp<T>::sp(const sp<T>& other)
    357     : m_ptr(other.m_ptr)
    358 {
    359     if (m_ptr) m_ptr->incStrong(this);
    360 }
    361 
    362 template<typename T> template<typename U>
    363 sp<T>::sp(U* other) : m_ptr(other)
    364 {
    365     if (other) other->incStrong(this);
    366 }
    367 
    368 template<typename T> template<typename U>
    369 sp<T>::sp(const sp<U>& other)
    370     : m_ptr(other.m_ptr)
    371 {
    372     if (m_ptr) m_ptr->incStrong(this);
    373 }
    374 
    375 template<typename T>
    376 sp<T>::~sp()
    377 {
    378     if (m_ptr) m_ptr->decStrong(this);
    379 }
    380 
    381 template<typename T>
    382 sp<T>& sp<T>::operator = (const sp<T>& other) {
    383     T* otherPtr(other.m_ptr);
    384     if (otherPtr) otherPtr->incStrong(this);
    385     if (m_ptr) m_ptr->decStrong(this);
    386     m_ptr = otherPtr;
    387     return *this;
    388 }
    389 
    390 template<typename T>
    391 sp<T>& sp<T>::operator = (T* other)
    392 {
    393     if (other) other->incStrong(this);
    394     if (m_ptr) m_ptr->decStrong(this);
    395     m_ptr = other;
    396     return *this;
    397 }
    398 
    399 template<typename T> template<typename U>
    400 sp<T>& sp<T>::operator = (const sp<U>& other)
    401 {
    402     U* otherPtr(other.m_ptr);
    403     if (otherPtr) otherPtr->incStrong(this);
    404     if (m_ptr) m_ptr->decStrong(this);
    405     m_ptr = otherPtr;
    406     return *this;
    407 }
    408 
    409 template<typename T> template<typename U>
    410 sp<T>& sp<T>::operator = (U* other)
    411 {
    412     if (other) other->incStrong(this);
    413     if (m_ptr) m_ptr->decStrong(this);
    414     m_ptr = other;
    415     return *this;
    416 }
    417 
    418 template<typename T>
    419 void sp<T>::force_set(T* other)
    420 {
    421     other->forceIncStrong(this);
    422     m_ptr = other;
    423 }
    424 
    425 template<typename T>
    426 void sp<T>::clear()
    427 {
    428     if (m_ptr) {
    429         m_ptr->decStrong(this);
    430         m_ptr = 0;
    431     }
    432 }
    433 
    434 template<typename T>
    435 sp<T>::sp(T* p, weakref_type* refs)
    436     : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
    437 {
    438 }
    439 
    440 template <typename T>
    441 inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
    442 {
    443     to << "sp<>(" << val.get() << ")";
    444     return to;
    445 }
    446 
    447 // ---------------------------------------------------------------------------
    448 
    449 template<typename T>
    450 wp<T>::wp(T* other)
    451     : m_ptr(other)
    452 {
    453     if (other) m_refs = other->createWeak(this);
    454 }
    455 
    456 template<typename T>
    457 wp<T>::wp(const wp<T>& other)
    458     : m_ptr(other.m_ptr), m_refs(other.m_refs)
    459 {
    460     if (m_ptr) m_refs->incWeak(this);
    461 }
    462 
    463 template<typename T>
    464 wp<T>::wp(const sp<T>& other)
    465     : m_ptr(other.m_ptr)
    466 {
    467     if (m_ptr) {
    468         m_refs = m_ptr->createWeak(this);
    469     }
    470 }
    471 
    472 template<typename T> template<typename U>
    473 wp<T>::wp(U* other)
    474     : m_ptr(other)
    475 {
    476     if (other) m_refs = other->createWeak(this);
    477 }
    478 
    479 template<typename T> template<typename U>
    480 wp<T>::wp(const wp<U>& other)
    481     : m_ptr(other.m_ptr)
    482 {
    483     if (m_ptr) {
    484         m_refs = other.m_refs;
    485         m_refs->incWeak(this);
    486     }
    487 }
    488 
    489 template<typename T> template<typename U>
    490 wp<T>::wp(const sp<U>& other)
    491     : m_ptr(other.m_ptr)
    492 {
    493     if (m_ptr) {
    494         m_refs = m_ptr->createWeak(this);
    495     }
    496 }
    497 
    498 template<typename T>
    499 wp<T>::~wp()
    500 {
    501     if (m_ptr) m_refs->decWeak(this);
    502 }
    503 
    504 template<typename T>
    505 wp<T>& wp<T>::operator = (T* other)
    506 {
    507     weakref_type* newRefs =
    508         other ? other->createWeak(this) : 0;
    509     if (m_ptr) m_refs->decWeak(this);
    510     m_ptr = other;
    511     m_refs = newRefs;
    512     return *this;
    513 }
    514 
    515 template<typename T>
    516 wp<T>& wp<T>::operator = (const wp<T>& other)
    517 {
    518     weakref_type* otherRefs(other.m_refs);
    519     T* otherPtr(other.m_ptr);
    520     if (otherPtr) otherRefs->incWeak(this);
    521     if (m_ptr) m_refs->decWeak(this);
    522     m_ptr = otherPtr;
    523     m_refs = otherRefs;
    524     return *this;
    525 }
    526 
    527 template<typename T>
    528 wp<T>& wp<T>::operator = (const sp<T>& other)
    529 {
    530     weakref_type* newRefs =
    531         other != NULL ? other->createWeak(this) : 0;
    532     T* otherPtr(other.m_ptr);
    533     if (m_ptr) m_refs->decWeak(this);
    534     m_ptr = otherPtr;
    535     m_refs = newRefs;
    536     return *this;
    537 }
    538 
    539 template<typename T> template<typename U>
    540 wp<T>& wp<T>::operator = (U* other)
    541 {
    542     weakref_type* newRefs =
    543         other ? other->createWeak(this) : 0;
    544     if (m_ptr) m_refs->decWeak(this);
    545     m_ptr = other;
    546     m_refs = newRefs;
    547     return *this;
    548 }
    549 
    550 template<typename T> template<typename U>
    551 wp<T>& wp<T>::operator = (const wp<U>& other)
    552 {
    553     weakref_type* otherRefs(other.m_refs);
    554     U* otherPtr(other.m_ptr);
    555     if (otherPtr) otherRefs->incWeak(this);
    556     if (m_ptr) m_refs->decWeak(this);
    557     m_ptr = otherPtr;
    558     m_refs = otherRefs;
    559     return *this;
    560 }
    561 
    562 template<typename T> template<typename U>
    563 wp<T>& wp<T>::operator = (const sp<U>& other)
    564 {
    565     weakref_type* newRefs =
    566         other != NULL ? other->createWeak(this) : 0;
    567     U* otherPtr(other.m_ptr);
    568     if (m_ptr) m_refs->decWeak(this);
    569     m_ptr = otherPtr;
    570     m_refs = newRefs;
    571     return *this;
    572 }
    573 
    574 template<typename T>
    575 void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
    576 {
    577     if (other) refs->incWeak(this);
    578     if (m_ptr) m_refs->decWeak(this);
    579     m_ptr = other;
    580     m_refs = refs;
    581 }
    582 
    583 template<typename T>
    584 sp<T> wp<T>::promote() const
    585 {
    586     return sp<T>(m_ptr, m_refs);
    587 }
    588 
    589 template<typename T>
    590 void wp<T>::clear()
    591 {
    592     if (m_ptr) {
    593         m_refs->decWeak(this);
    594         m_ptr = 0;
    595     }
    596 }
    597 
    598 template <typename T>
    599 inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
    600 {
    601     to << "wp<>(" << val.unsafe_get() << ")";
    602     return to;
    603 }
    604 
    605 }; // namespace android
    606 
    607 // ---------------------------------------------------------------------------
    608 
    609 #endif // ANDROID_REF_BASE_H
    610