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(_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 wp<T>& o) const {              \
     39     return m_ptr _op_ o.m_ptr;                                  \
     40 }                                                               \
     41 inline bool operator _op_ (const T* o) const {                  \
     42     return m_ptr _op_ o;                                        \
     43 }                                                               \
     44 template<typename U>                                            \
     45 inline bool operator _op_ (const sp<U>& o) const {              \
     46     return m_ptr _op_ o.m_ptr;                                  \
     47 }                                                               \
     48 template<typename U>                                            \
     49 inline bool operator _op_ (const wp<U>& o) const {              \
     50     return m_ptr _op_ o.m_ptr;                                  \
     51 }                                                               \
     52 template<typename U>                                            \
     53 inline bool operator _op_ (const U* o) const {                  \
     54     return m_ptr _op_ o;                                        \
     55 }
     56 
     57 // ---------------------------------------------------------------------------
     58 
     59 class RefBase
     60 {
     61 public:
     62             void            incStrong(const void* id) const;
     63             void            decStrong(const void* id) const;
     64 
     65             void            forceIncStrong(const void* id) const;
     66 
     67             //! DEBUGGING ONLY: Get current strong ref count.
     68             int32_t         getStrongCount() const;
     69 
     70     class weakref_type
     71     {
     72     public:
     73         RefBase*            refBase() const;
     74 
     75         void                incWeak(const void* id);
     76         void                decWeak(const void* id);
     77 
     78         bool                attemptIncStrong(const void* id);
     79 
     80         //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
     81         bool                attemptIncWeak(const void* id);
     82 
     83         //! DEBUGGING ONLY: Get current weak ref count.
     84         int32_t             getWeakCount() const;
     85 
     86         //! DEBUGGING ONLY: Print references held on object.
     87         void                printRefs() const;
     88 
     89         //! DEBUGGING ONLY: Enable tracking for this object.
     90         // enable -- enable/disable tracking
     91         // retain -- when tracking is enable, if true, then we save a stack trace
     92         //           for each reference and dereference; when retain == false, we
     93         //           match up references and dereferences and keep only the
     94         //           outstanding ones.
     95 
     96         void                trackMe(bool enable, bool retain);
     97     };
     98 
     99             weakref_type*   createWeak(const void* id) const;
    100 
    101             weakref_type*   getWeakRefs() const;
    102 
    103             //! DEBUGGING ONLY: Print references held on object.
    104     inline  void            printRefs() const { getWeakRefs()->printRefs(); }
    105 
    106             //! DEBUGGING ONLY: Enable tracking of object.
    107     inline  void            trackMe(bool enable, bool retain)
    108     {
    109         getWeakRefs()->trackMe(enable, retain);
    110     }
    111 
    112 protected:
    113                             RefBase();
    114     virtual                 ~RefBase();
    115 
    116     //! Flags for extendObjectLifetime()
    117     enum {
    118         OBJECT_LIFETIME_WEAK    = 0x0001,
    119         OBJECT_LIFETIME_FOREVER = 0x0003
    120     };
    121 
    122             void            extendObjectLifetime(int32_t mode);
    123 
    124     //! Flags for onIncStrongAttempted()
    125     enum {
    126         FIRST_INC_STRONG = 0x0001
    127     };
    128 
    129     virtual void            onFirstRef();
    130     virtual void            onLastStrongRef(const void* id);
    131     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    132     virtual void            onLastWeakRef(const void* id);
    133 
    134 private:
    135     friend class weakref_type;
    136     class weakref_impl;
    137 
    138                             RefBase(const RefBase& o);
    139             RefBase&        operator=(const RefBase& o);
    140 
    141         weakref_impl* const mRefs;
    142 };
    143 
    144 // ---------------------------------------------------------------------------
    145 
    146 template <class T>
    147 class LightRefBase
    148 {
    149 public:
    150     inline LightRefBase() : mCount(0) { }
    151     inline void incStrong(const void* id) const {
    152         android_atomic_inc(&mCount);
    153     }
    154     inline void decStrong(const void* id) const {
    155         if (android_atomic_dec(&mCount) == 1) {
    156             delete static_cast<const T*>(this);
    157         }
    158     }
    159     //! DEBUGGING ONLY: Get current strong ref count.
    160     inline int32_t getStrongCount() const {
    161         return mCount;
    162     }
    163 
    164 protected:
    165     inline ~LightRefBase() { }
    166 
    167 private:
    168     mutable volatile int32_t mCount;
    169 };
    170 
    171 // ---------------------------------------------------------------------------
    172 
    173 template <typename T>
    174 class sp
    175 {
    176 public:
    177     typedef typename RefBase::weakref_type weakref_type;
    178 
    179     inline sp() : m_ptr(0) { }
    180 
    181     sp(T* other);
    182     sp(const sp<T>& other);
    183     template<typename U> sp(U* other);
    184     template<typename U> sp(const sp<U>& other);
    185 
    186     ~sp();
    187 
    188     // Assignment
    189 
    190     sp& operator = (T* other);
    191     sp& operator = (const sp<T>& other);
    192 
    193     template<typename U> sp& operator = (const sp<U>& other);
    194     template<typename U> sp& operator = (U* other);
    195 
    196     //! Special optimization for use by ProcessState (and nobody else).
    197     void force_set(T* other);
    198 
    199     // Reset
    200 
    201     void clear();
    202 
    203     // Accessors
    204 
    205     inline  T&      operator* () const  { return *m_ptr; }
    206     inline  T*      operator-> () const { return m_ptr;  }
    207     inline  T*      get() const         { return m_ptr; }
    208 
    209     // Operators
    210 
    211     COMPARE(==)
    212     COMPARE(!=)
    213     COMPARE(>)
    214     COMPARE(<)
    215     COMPARE(<=)
    216     COMPARE(>=)
    217 
    218 private:
    219     template<typename Y> friend class sp;
    220     template<typename Y> friend class wp;
    221 
    222     // Optimization for wp::promote().
    223     sp(T* p, weakref_type* refs);
    224 
    225     T*              m_ptr;
    226 };
    227 
    228 template <typename T>
    229 TextOutput& operator<<(TextOutput& to, const sp<T>& val);
    230 
    231 // ---------------------------------------------------------------------------
    232 
    233 template <typename T>
    234 class wp
    235 {
    236 public:
    237     typedef typename RefBase::weakref_type weakref_type;
    238 
    239     inline wp() : m_ptr(0) { }
    240 
    241     wp(T* other);
    242     wp(const wp<T>& other);
    243     wp(const sp<T>& other);
    244     template<typename U> wp(U* other);
    245     template<typename U> wp(const sp<U>& other);
    246     template<typename U> wp(const wp<U>& other);
    247 
    248     ~wp();
    249 
    250     // Assignment
    251 
    252     wp& operator = (T* other);
    253     wp& operator = (const wp<T>& other);
    254     wp& operator = (const sp<T>& other);
    255 
    256     template<typename U> wp& operator = (U* other);
    257     template<typename U> wp& operator = (const wp<U>& other);
    258     template<typename U> wp& operator = (const sp<U>& other);
    259 
    260     void set_object_and_refs(T* other, weakref_type* refs);
    261 
    262     // promotion to sp
    263 
    264     sp<T> promote() const;
    265 
    266     // Reset
    267 
    268     void clear();
    269 
    270     // Accessors
    271 
    272     inline  weakref_type* get_refs() const { return m_refs; }
    273 
    274     inline  T* unsafe_get() const { return m_ptr; }
    275 
    276     // Operators
    277 
    278     COMPARE(==)
    279     COMPARE(!=)
    280     COMPARE(>)
    281     COMPARE(<)
    282     COMPARE(<=)
    283     COMPARE(>=)
    284 
    285 private:
    286     template<typename Y> friend class sp;
    287     template<typename Y> friend class wp;
    288 
    289     T*              m_ptr;
    290     weakref_type*   m_refs;
    291 };
    292 
    293 template <typename T>
    294 TextOutput& operator<<(TextOutput& to, const wp<T>& val);
    295 
    296 #undef COMPARE
    297 
    298 // ---------------------------------------------------------------------------
    299 // No user serviceable parts below here.
    300 
    301 template<typename T>
    302 sp<T>::sp(T* other)
    303     : m_ptr(other)
    304 {
    305     if (other) other->incStrong(this);
    306 }
    307 
    308 template<typename T>
    309 sp<T>::sp(const sp<T>& other)
    310     : m_ptr(other.m_ptr)
    311 {
    312     if (m_ptr) m_ptr->incStrong(this);
    313 }
    314 
    315 template<typename T> template<typename U>
    316 sp<T>::sp(U* other) : m_ptr(other)
    317 {
    318     if (other) other->incStrong(this);
    319 }
    320 
    321 template<typename T> template<typename U>
    322 sp<T>::sp(const sp<U>& other)
    323     : m_ptr(other.m_ptr)
    324 {
    325     if (m_ptr) m_ptr->incStrong(this);
    326 }
    327 
    328 template<typename T>
    329 sp<T>::~sp()
    330 {
    331     if (m_ptr) m_ptr->decStrong(this);
    332 }
    333 
    334 template<typename T>
    335 sp<T>& sp<T>::operator = (const sp<T>& other) {
    336     if (other.m_ptr) other.m_ptr->incStrong(this);
    337     if (m_ptr) m_ptr->decStrong(this);
    338     m_ptr = other.m_ptr;
    339     return *this;
    340 }
    341 
    342 template<typename T>
    343 sp<T>& sp<T>::operator = (T* other)
    344 {
    345     if (other) other->incStrong(this);
    346     if (m_ptr) m_ptr->decStrong(this);
    347     m_ptr = other;
    348     return *this;
    349 }
    350 
    351 template<typename T> template<typename U>
    352 sp<T>& sp<T>::operator = (const sp<U>& other)
    353 {
    354     if (other.m_ptr) other.m_ptr->incStrong(this);
    355     if (m_ptr) m_ptr->decStrong(this);
    356     m_ptr = other.m_ptr;
    357     return *this;
    358 }
    359 
    360 template<typename T> template<typename U>
    361 sp<T>& sp<T>::operator = (U* other)
    362 {
    363     if (other) other->incStrong(this);
    364     if (m_ptr) m_ptr->decStrong(this);
    365     m_ptr = other;
    366     return *this;
    367 }
    368 
    369 template<typename T>
    370 void sp<T>::force_set(T* other)
    371 {
    372     other->forceIncStrong(this);
    373     m_ptr = other;
    374 }
    375 
    376 template<typename T>
    377 void sp<T>::clear()
    378 {
    379     if (m_ptr) {
    380         m_ptr->decStrong(this);
    381         m_ptr = 0;
    382     }
    383 }
    384 
    385 template<typename T>
    386 sp<T>::sp(T* p, weakref_type* refs)
    387     : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
    388 {
    389 }
    390 
    391 template <typename T>
    392 inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
    393 {
    394     to << "sp<>(" << val.get() << ")";
    395     return to;
    396 }
    397 
    398 // ---------------------------------------------------------------------------
    399 
    400 template<typename T>
    401 wp<T>::wp(T* other)
    402     : m_ptr(other)
    403 {
    404     if (other) m_refs = other->createWeak(this);
    405 }
    406 
    407 template<typename T>
    408 wp<T>::wp(const wp<T>& other)
    409     : m_ptr(other.m_ptr), m_refs(other.m_refs)
    410 {
    411     if (m_ptr) m_refs->incWeak(this);
    412 }
    413 
    414 template<typename T>
    415 wp<T>::wp(const sp<T>& other)
    416     : m_ptr(other.m_ptr)
    417 {
    418     if (m_ptr) {
    419         m_refs = m_ptr->createWeak(this);
    420     }
    421 }
    422 
    423 template<typename T> template<typename U>
    424 wp<T>::wp(U* other)
    425     : m_ptr(other)
    426 {
    427     if (other) m_refs = other->createWeak(this);
    428 }
    429 
    430 template<typename T> template<typename U>
    431 wp<T>::wp(const wp<U>& other)
    432     : m_ptr(other.m_ptr)
    433 {
    434     if (m_ptr) {
    435         m_refs = other.m_refs;
    436         m_refs->incWeak(this);
    437     }
    438 }
    439 
    440 template<typename T> template<typename U>
    441 wp<T>::wp(const sp<U>& other)
    442     : m_ptr(other.m_ptr)
    443 {
    444     if (m_ptr) {
    445         m_refs = m_ptr->createWeak(this);
    446     }
    447 }
    448 
    449 template<typename T>
    450 wp<T>::~wp()
    451 {
    452     if (m_ptr) m_refs->decWeak(this);
    453 }
    454 
    455 template<typename T>
    456 wp<T>& wp<T>::operator = (T* other)
    457 {
    458     weakref_type* newRefs =
    459         other ? other->createWeak(this) : 0;
    460     if (m_ptr) m_refs->decWeak(this);
    461     m_ptr = other;
    462     m_refs = newRefs;
    463     return *this;
    464 }
    465 
    466 template<typename T>
    467 wp<T>& wp<T>::operator = (const wp<T>& other)
    468 {
    469     if (other.m_ptr) other.m_refs->incWeak(this);
    470     if (m_ptr) m_refs->decWeak(this);
    471     m_ptr = other.m_ptr;
    472     m_refs = other.m_refs;
    473     return *this;
    474 }
    475 
    476 template<typename T>
    477 wp<T>& wp<T>::operator = (const sp<T>& other)
    478 {
    479     weakref_type* newRefs =
    480         other != NULL ? other->createWeak(this) : 0;
    481     if (m_ptr) m_refs->decWeak(this);
    482     m_ptr = other.get();
    483     m_refs = newRefs;
    484     return *this;
    485 }
    486 
    487 template<typename T> template<typename U>
    488 wp<T>& wp<T>::operator = (U* other)
    489 {
    490     weakref_type* newRefs =
    491         other ? other->createWeak(this) : 0;
    492     if (m_ptr) m_refs->decWeak(this);
    493     m_ptr = other;
    494     m_refs = newRefs;
    495     return *this;
    496 }
    497 
    498 template<typename T> template<typename U>
    499 wp<T>& wp<T>::operator = (const wp<U>& other)
    500 {
    501     if (other.m_ptr) other.m_refs->incWeak(this);
    502     if (m_ptr) m_refs->decWeak(this);
    503     m_ptr = other.m_ptr;
    504     m_refs = other.m_refs;
    505     return *this;
    506 }
    507 
    508 template<typename T> template<typename U>
    509 wp<T>& wp<T>::operator = (const sp<U>& other)
    510 {
    511     weakref_type* newRefs =
    512         other != NULL ? other->createWeak(this) : 0;
    513     if (m_ptr) m_refs->decWeak(this);
    514     m_ptr = other.get();
    515     m_refs = newRefs;
    516     return *this;
    517 }
    518 
    519 template<typename T>
    520 void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
    521 {
    522     if (other) refs->incWeak(this);
    523     if (m_ptr) m_refs->decWeak(this);
    524     m_ptr = other;
    525     m_refs = refs;
    526 }
    527 
    528 template<typename T>
    529 sp<T> wp<T>::promote() const
    530 {
    531     return sp<T>(m_ptr, m_refs);
    532 }
    533 
    534 template<typename T>
    535 void wp<T>::clear()
    536 {
    537     if (m_ptr) {
    538         m_refs->decWeak(this);
    539         m_ptr = 0;
    540     }
    541 }
    542 
    543 template <typename T>
    544 inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
    545 {
    546     to << "wp<>(" << val.unsafe_get() << ")";
    547     return to;
    548 }
    549 
    550 }; // namespace android
    551 
    552 // ---------------------------------------------------------------------------
    553 
    554 #endif // ANDROID_REF_BASE_H
    555