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 
     22 #include <stdint.h>
     23 #include <sys/types.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 
     27 #include <utils/StrongPointer.h>
     28 
     29 // ---------------------------------------------------------------------------
     30 namespace android {
     31 
     32 class TextOutput;
     33 TextOutput& printWeakPointer(TextOutput& to, const void* val);
     34 
     35 // ---------------------------------------------------------------------------
     36 
     37 #define COMPARE_WEAK(_op_)                                      \
     38 inline bool operator _op_ (const sp<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 U* o) const {                  \
     50     return m_ptr _op_ o;                                        \
     51 }
     52 
     53 // ---------------------------------------------------------------------------
     54 class ReferenceMover;
     55 class ReferenceConverterBase {
     56 public:
     57     virtual size_t getReferenceTypeSize() const = 0;
     58     virtual void* getReferenceBase(void const*) const = 0;
     59     inline virtual ~ReferenceConverterBase() { }
     60 };
     61 
     62 // ---------------------------------------------------------------------------
     63 
     64 class RefBase
     65 {
     66 public:
     67             void            incStrong(const void* id) const;
     68             void            decStrong(const void* id) const;
     69 
     70             void            forceIncStrong(const void* id) const;
     71 
     72             //! DEBUGGING ONLY: Get current strong ref count.
     73             int32_t         getStrongCount() const;
     74 
     75     class weakref_type
     76     {
     77     public:
     78         RefBase*            refBase() const;
     79 
     80         void                incWeak(const void* id);
     81         void                decWeak(const void* id);
     82 
     83         // acquires a strong reference if there is already one.
     84         bool                attemptIncStrong(const void* id);
     85 
     86         // acquires a weak reference if there is already one.
     87         // This is not always safe. see ProcessState.cpp and BpBinder.cpp
     88         // for proper use.
     89         bool                attemptIncWeak(const void* id);
     90 
     91         //! DEBUGGING ONLY: Get current weak ref count.
     92         int32_t             getWeakCount() const;
     93 
     94         //! DEBUGGING ONLY: Print references held on object.
     95         void                printRefs() const;
     96 
     97         //! DEBUGGING ONLY: Enable tracking for this object.
     98         // enable -- enable/disable tracking
     99         // retain -- when tracking is enable, if true, then we save a stack trace
    100         //           for each reference and dereference; when retain == false, we
    101         //           match up references and dereferences and keep only the
    102         //           outstanding ones.
    103 
    104         void                trackMe(bool enable, bool retain);
    105     };
    106 
    107             weakref_type*   createWeak(const void* id) const;
    108 
    109             weakref_type*   getWeakRefs() const;
    110 
    111             //! DEBUGGING ONLY: Print references held on object.
    112     inline  void            printRefs() const { getWeakRefs()->printRefs(); }
    113 
    114             //! DEBUGGING ONLY: Enable tracking of object.
    115     inline  void            trackMe(bool enable, bool retain)
    116     {
    117         getWeakRefs()->trackMe(enable, retain);
    118     }
    119 
    120     typedef RefBase basetype;
    121 
    122 protected:
    123                             RefBase();
    124     virtual                 ~RefBase();
    125 
    126     //! Flags for extendObjectLifetime()
    127     enum {
    128         OBJECT_LIFETIME_STRONG  = 0x0000,
    129         OBJECT_LIFETIME_WEAK    = 0x0001,
    130         OBJECT_LIFETIME_MASK    = 0x0001
    131     };
    132 
    133             void            extendObjectLifetime(int32_t mode);
    134 
    135     //! Flags for onIncStrongAttempted()
    136     enum {
    137         FIRST_INC_STRONG = 0x0001
    138     };
    139 
    140     virtual void            onFirstRef();
    141     virtual void            onLastStrongRef(const void* id);
    142     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    143     virtual void            onLastWeakRef(const void* id);
    144 
    145 private:
    146     friend class ReferenceMover;
    147     static void moveReferences(void* d, void const* s, size_t n,
    148             const ReferenceConverterBase& caster);
    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     typedef LightRefBase<T> basetype;
    181 
    182 protected:
    183     inline ~LightRefBase() { }
    184 
    185 private:
    186     friend class ReferenceMover;
    187     inline static void moveReferences(void* d, void const* s, size_t n,
    188             const ReferenceConverterBase& caster) { }
    189 
    190 private:
    191     mutable volatile int32_t mCount;
    192 };
    193 
    194 // ---------------------------------------------------------------------------
    195 
    196 template <typename T>
    197 class wp
    198 {
    199 public:
    200     typedef typename RefBase::weakref_type weakref_type;
    201 
    202     inline wp() : m_ptr(0) { }
    203 
    204     wp(T* other);
    205     wp(const wp<T>& other);
    206     wp(const sp<T>& other);
    207     template<typename U> wp(U* other);
    208     template<typename U> wp(const sp<U>& other);
    209     template<typename U> wp(const wp<U>& other);
    210 
    211     ~wp();
    212 
    213     // Assignment
    214 
    215     wp& operator = (T* other);
    216     wp& operator = (const wp<T>& other);
    217     wp& operator = (const sp<T>& other);
    218 
    219     template<typename U> wp& operator = (U* other);
    220     template<typename U> wp& operator = (const wp<U>& other);
    221     template<typename U> wp& operator = (const sp<U>& other);
    222 
    223     void set_object_and_refs(T* other, weakref_type* refs);
    224 
    225     // promotion to sp
    226 
    227     sp<T> promote() const;
    228 
    229     // Reset
    230 
    231     void clear();
    232 
    233     // Accessors
    234 
    235     inline  weakref_type* get_refs() const { return m_refs; }
    236 
    237     inline  T* unsafe_get() const { return m_ptr; }
    238 
    239     // Operators
    240 
    241     COMPARE_WEAK(==)
    242     COMPARE_WEAK(!=)
    243     COMPARE_WEAK(>)
    244     COMPARE_WEAK(<)
    245     COMPARE_WEAK(<=)
    246     COMPARE_WEAK(>=)
    247 
    248     inline bool operator == (const wp<T>& o) const {
    249         return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
    250     }
    251     template<typename U>
    252     inline bool operator == (const wp<U>& o) const {
    253         return m_ptr == o.m_ptr;
    254     }
    255 
    256     inline bool operator > (const wp<T>& o) const {
    257         return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    258     }
    259     template<typename U>
    260     inline bool operator > (const wp<U>& o) const {
    261         return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    262     }
    263 
    264     inline bool operator < (const wp<T>& o) const {
    265         return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    266     }
    267     template<typename U>
    268     inline bool operator < (const wp<U>& o) const {
    269         return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    270     }
    271                          inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
    272     template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
    273                          inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
    274     template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
    275                          inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
    276     template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
    277 
    278 private:
    279     template<typename Y> friend class sp;
    280     template<typename Y> friend class wp;
    281 
    282     T*              m_ptr;
    283     weakref_type*   m_refs;
    284 };
    285 
    286 template <typename T>
    287 TextOutput& operator<<(TextOutput& to, const wp<T>& val);
    288 
    289 #undef COMPARE_WEAK
    290 
    291 // ---------------------------------------------------------------------------
    292 // No user serviceable parts below here.
    293 
    294 template<typename T>
    295 wp<T>::wp(T* other)
    296     : m_ptr(other)
    297 {
    298     if (other) m_refs = other->createWeak(this);
    299 }
    300 
    301 template<typename T>
    302 wp<T>::wp(const wp<T>& other)
    303     : m_ptr(other.m_ptr), m_refs(other.m_refs)
    304 {
    305     if (m_ptr) m_refs->incWeak(this);
    306 }
    307 
    308 template<typename T>
    309 wp<T>::wp(const sp<T>& other)
    310     : m_ptr(other.m_ptr)
    311 {
    312     if (m_ptr) {
    313         m_refs = m_ptr->createWeak(this);
    314     }
    315 }
    316 
    317 template<typename T> template<typename U>
    318 wp<T>::wp(U* other)
    319     : m_ptr(other)
    320 {
    321     if (other) m_refs = other->createWeak(this);
    322 }
    323 
    324 template<typename T> template<typename U>
    325 wp<T>::wp(const wp<U>& other)
    326     : m_ptr(other.m_ptr)
    327 {
    328     if (m_ptr) {
    329         m_refs = other.m_refs;
    330         m_refs->incWeak(this);
    331     }
    332 }
    333 
    334 template<typename T> template<typename U>
    335 wp<T>::wp(const sp<U>& other)
    336     : m_ptr(other.m_ptr)
    337 {
    338     if (m_ptr) {
    339         m_refs = m_ptr->createWeak(this);
    340     }
    341 }
    342 
    343 template<typename T>
    344 wp<T>::~wp()
    345 {
    346     if (m_ptr) m_refs->decWeak(this);
    347 }
    348 
    349 template<typename T>
    350 wp<T>& wp<T>::operator = (T* other)
    351 {
    352     weakref_type* newRefs =
    353         other ? other->createWeak(this) : 0;
    354     if (m_ptr) m_refs->decWeak(this);
    355     m_ptr = other;
    356     m_refs = newRefs;
    357     return *this;
    358 }
    359 
    360 template<typename T>
    361 wp<T>& wp<T>::operator = (const wp<T>& other)
    362 {
    363     weakref_type* otherRefs(other.m_refs);
    364     T* otherPtr(other.m_ptr);
    365     if (otherPtr) otherRefs->incWeak(this);
    366     if (m_ptr) m_refs->decWeak(this);
    367     m_ptr = otherPtr;
    368     m_refs = otherRefs;
    369     return *this;
    370 }
    371 
    372 template<typename T>
    373 wp<T>& wp<T>::operator = (const sp<T>& other)
    374 {
    375     weakref_type* newRefs =
    376         other != NULL ? other->createWeak(this) : 0;
    377     T* otherPtr(other.m_ptr);
    378     if (m_ptr) m_refs->decWeak(this);
    379     m_ptr = otherPtr;
    380     m_refs = newRefs;
    381     return *this;
    382 }
    383 
    384 template<typename T> template<typename U>
    385 wp<T>& wp<T>::operator = (U* other)
    386 {
    387     weakref_type* newRefs =
    388         other ? other->createWeak(this) : 0;
    389     if (m_ptr) m_refs->decWeak(this);
    390     m_ptr = other;
    391     m_refs = newRefs;
    392     return *this;
    393 }
    394 
    395 template<typename T> template<typename U>
    396 wp<T>& wp<T>::operator = (const wp<U>& other)
    397 {
    398     weakref_type* otherRefs(other.m_refs);
    399     U* otherPtr(other.m_ptr);
    400     if (otherPtr) otherRefs->incWeak(this);
    401     if (m_ptr) m_refs->decWeak(this);
    402     m_ptr = otherPtr;
    403     m_refs = otherRefs;
    404     return *this;
    405 }
    406 
    407 template<typename T> template<typename U>
    408 wp<T>& wp<T>::operator = (const sp<U>& other)
    409 {
    410     weakref_type* newRefs =
    411         other != NULL ? other->createWeak(this) : 0;
    412     U* otherPtr(other.m_ptr);
    413     if (m_ptr) m_refs->decWeak(this);
    414     m_ptr = otherPtr;
    415     m_refs = newRefs;
    416     return *this;
    417 }
    418 
    419 template<typename T>
    420 void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
    421 {
    422     if (other) refs->incWeak(this);
    423     if (m_ptr) m_refs->decWeak(this);
    424     m_ptr = other;
    425     m_refs = refs;
    426 }
    427 
    428 template<typename T>
    429 sp<T> wp<T>::promote() const
    430 {
    431     sp<T> result;
    432     if (m_ptr && m_refs->attemptIncStrong(&result)) {
    433         result.set_pointer(m_ptr);
    434     }
    435     return result;
    436 }
    437 
    438 template<typename T>
    439 void wp<T>::clear()
    440 {
    441     if (m_ptr) {
    442         m_refs->decWeak(this);
    443         m_ptr = 0;
    444     }
    445 }
    446 
    447 template <typename T>
    448 inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
    449 {
    450     return printWeakPointer(to, val.unsafe_get());
    451 }
    452 
    453 // ---------------------------------------------------------------------------
    454 
    455 // this class just serves as a namespace so TYPE::moveReferences can stay
    456 // private.
    457 
    458 class ReferenceMover {
    459     // StrongReferenceCast and WeakReferenceCast do the impedance matching
    460     // between the generic (void*) implementation in Refbase and the strongly typed
    461     // template specializations below.
    462 
    463     template <typename TYPE>
    464     struct StrongReferenceCast : public ReferenceConverterBase {
    465         virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
    466         virtual void* getReferenceBase(void const* p) const {
    467             sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
    468             return static_cast<typename TYPE::basetype *>(sptr->get());
    469         }
    470     };
    471 
    472     template <typename TYPE>
    473     struct WeakReferenceCast : public ReferenceConverterBase {
    474         virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
    475         virtual void* getReferenceBase(void const* p) const {
    476             wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
    477             return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
    478         }
    479     };
    480 
    481 public:
    482     template<typename TYPE> static inline
    483     void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
    484         memmove(d, s, n*sizeof(sp<TYPE>));
    485         StrongReferenceCast<TYPE> caster;
    486         TYPE::moveReferences(d, s, n, caster);
    487     }
    488     template<typename TYPE> static inline
    489     void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
    490         memmove(d, s, n*sizeof(wp<TYPE>));
    491         WeakReferenceCast<TYPE> caster;
    492         TYPE::moveReferences(d, s, n, caster);
    493     }
    494 };
    495 
    496 // specialization for moving sp<> and wp<> types.
    497 // these are used by the [Sorted|Keyed]Vector<> implementations
    498 // sp<> and wp<> need to be handled specially, because they do not
    499 // have trivial copy operation in the general case (see RefBase.cpp
    500 // when DEBUG ops are enabled), but can be implemented very
    501 // efficiently in most cases.
    502 
    503 template<typename TYPE> inline
    504 void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
    505     ReferenceMover::move_references(d, s, n);
    506 }
    507 
    508 template<typename TYPE> inline
    509 void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
    510     ReferenceMover::move_references(d, s, n);
    511 }
    512 
    513 template<typename TYPE> inline
    514 void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
    515     ReferenceMover::move_references(d, s, n);
    516 }
    517 
    518 template<typename TYPE> inline
    519 void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
    520     ReferenceMover::move_references(d, s, n);
    521 }
    522 
    523 
    524 }; // namespace android
    525 
    526 // ---------------------------------------------------------------------------
    527 
    528 #endif // ANDROID_REF_BASE_H
    529