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_STRONG_POINTER_H
     18 #define ANDROID_STRONG_POINTER_H
     19 
     20 // ---------------------------------------------------------------------------
     21 namespace android {
     22 
     23 template<typename T> class wp;
     24 
     25 // ---------------------------------------------------------------------------
     26 
     27 #define COMPARE(_op_)                                           \
     28 inline bool operator _op_ (const sp<T>& o) const {              \
     29     return m_ptr _op_ o.m_ptr;                                  \
     30 }                                                               \
     31 inline bool operator _op_ (const T* o) const {                  \
     32     return m_ptr _op_ o;                                        \
     33 }                                                               \
     34 template<typename U>                                            \
     35 inline bool operator _op_ (const sp<U>& o) const {              \
     36     return m_ptr _op_ o.m_ptr;                                  \
     37 }                                                               \
     38 template<typename U>                                            \
     39 inline bool operator _op_ (const U* o) const {                  \
     40     return m_ptr _op_ o;                                        \
     41 }                                                               \
     42 inline bool operator _op_ (const wp<T>& o) const {              \
     43     return m_ptr _op_ o.m_ptr;                                  \
     44 }                                                               \
     45 template<typename U>                                            \
     46 inline bool operator _op_ (const wp<U>& o) const {              \
     47     return m_ptr _op_ o.m_ptr;                                  \
     48 }
     49 
     50 // ---------------------------------------------------------------------------
     51 
     52 template<typename T>
     53 class sp {
     54 public:
     55     inline sp() : m_ptr(0) { }
     56 
     57     sp(T* other);  // NOLINT(implicit)
     58     sp(const sp<T>& other);
     59     sp(sp<T>&& other);
     60     template<typename U> sp(U* other);  // NOLINT(implicit)
     61     template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
     62     template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
     63 
     64     ~sp();
     65 
     66     // Assignment
     67 
     68     sp& operator = (T* other);
     69     sp& operator = (const sp<T>& other);
     70     sp& operator = (sp<T>&& other);
     71 
     72     template<typename U> sp& operator = (const sp<U>& other);
     73     template<typename U> sp& operator = (sp<U>&& other);
     74     template<typename U> sp& operator = (U* other);
     75 
     76     //! Special optimization for use by ProcessState (and nobody else).
     77     void force_set(T* other);
     78 
     79     // Reset
     80 
     81     void clear();
     82 
     83     // Accessors
     84 
     85     inline  T&      operator* () const  { return *m_ptr; }
     86     inline  T*      operator-> () const { return m_ptr;  }
     87     inline  T*      get() const         { return m_ptr; }
     88 
     89     // Operators
     90 
     91     COMPARE(==)
     92     COMPARE(!=)
     93     COMPARE(>)
     94     COMPARE(<)
     95     COMPARE(<=)
     96     COMPARE(>=)
     97 
     98 private:
     99     template<typename Y> friend class sp;
    100     template<typename Y> friend class wp;
    101     void set_pointer(T* ptr);
    102     T* m_ptr;
    103 };
    104 
    105 // For code size reasons, we do not want this inlined or templated.
    106 void sp_report_race();
    107 
    108 #undef COMPARE
    109 
    110 // ---------------------------------------------------------------------------
    111 // No user serviceable parts below here.
    112 
    113 template<typename T>
    114 sp<T>::sp(T* other)
    115         : m_ptr(other) {
    116     if (other)
    117         other->incStrong(this);
    118 }
    119 
    120 template<typename T>
    121 sp<T>::sp(const sp<T>& other)
    122         : m_ptr(other.m_ptr) {
    123     if (m_ptr)
    124         m_ptr->incStrong(this);
    125 }
    126 
    127 template<typename T>
    128 sp<T>::sp(sp<T>&& other)
    129         : m_ptr(other.m_ptr) {
    130     other.m_ptr = nullptr;
    131 }
    132 
    133 template<typename T> template<typename U>
    134 sp<T>::sp(U* other)
    135         : m_ptr(other) {
    136     if (other)
    137         (static_cast<T*>(other))->incStrong(this);
    138 }
    139 
    140 template<typename T> template<typename U>
    141 sp<T>::sp(const sp<U>& other)
    142         : m_ptr(other.m_ptr) {
    143     if (m_ptr)
    144         m_ptr->incStrong(this);
    145 }
    146 
    147 template<typename T> template<typename U>
    148 sp<T>::sp(sp<U>&& other)
    149         : m_ptr(other.m_ptr) {
    150     other.m_ptr = nullptr;
    151 }
    152 
    153 template<typename T>
    154 sp<T>::~sp() {
    155     if (m_ptr)
    156         m_ptr->decStrong(this);
    157 }
    158 
    159 template<typename T>
    160 sp<T>& sp<T>::operator =(const sp<T>& other) {
    161     // Force m_ptr to be read twice, to heuristically check for data races.
    162     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    163     T* otherPtr(other.m_ptr);
    164     if (otherPtr) otherPtr->incStrong(this);
    165     if (oldPtr) oldPtr->decStrong(this);
    166     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    167     m_ptr = otherPtr;
    168     return *this;
    169 }
    170 
    171 template<typename T>
    172 sp<T>& sp<T>::operator =(sp<T>&& other) {
    173     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    174     if (oldPtr) oldPtr->decStrong(this);
    175     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    176     m_ptr = other.m_ptr;
    177     other.m_ptr = nullptr;
    178     return *this;
    179 }
    180 
    181 template<typename T>
    182 sp<T>& sp<T>::operator =(T* other) {
    183     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    184     if (other) other->incStrong(this);
    185     if (oldPtr) oldPtr->decStrong(this);
    186     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    187     m_ptr = other;
    188     return *this;
    189 }
    190 
    191 template<typename T> template<typename U>
    192 sp<T>& sp<T>::operator =(const sp<U>& other) {
    193     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    194     T* otherPtr(other.m_ptr);
    195     if (otherPtr) otherPtr->incStrong(this);
    196     if (oldPtr) oldPtr->decStrong(this);
    197     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    198     m_ptr = otherPtr;
    199     return *this;
    200 }
    201 
    202 template<typename T> template<typename U>
    203 sp<T>& sp<T>::operator =(sp<U>&& other) {
    204     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    205     if (m_ptr) m_ptr->decStrong(this);
    206     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    207     m_ptr = other.m_ptr;
    208     other.m_ptr = nullptr;
    209     return *this;
    210 }
    211 
    212 template<typename T> template<typename U>
    213 sp<T>& sp<T>::operator =(U* other) {
    214     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    215     if (other) (static_cast<T*>(other))->incStrong(this);
    216     if (oldPtr) oldPtr->decStrong(this);
    217     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    218     m_ptr = other;
    219     return *this;
    220 }
    221 
    222 template<typename T>
    223 void sp<T>::force_set(T* other) {
    224     other->forceIncStrong(this);
    225     m_ptr = other;
    226 }
    227 
    228 template<typename T>
    229 void sp<T>::clear() {
    230     if (m_ptr) {
    231         m_ptr->decStrong(this);
    232         m_ptr = 0;
    233     }
    234 }
    235 
    236 template<typename T>
    237 void sp<T>::set_pointer(T* ptr) {
    238     m_ptr = ptr;
    239 }
    240 
    241 }; // namespace android
    242 
    243 // ---------------------------------------------------------------------------
    244 
    245 #endif // ANDROID_STRONG_POINTER_H
    246