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     inline explicit operator bool () const { return m_ptr != nullptr; }
     89 
     90     // Operators
     91 
     92     COMPARE(==)
     93     COMPARE(!=)
     94     COMPARE(>)
     95     COMPARE(<)
     96     COMPARE(<=)
     97     COMPARE(>=)
     98 
     99 private:
    100     template<typename Y> friend class sp;
    101     template<typename Y> friend class wp;
    102     void set_pointer(T* ptr);
    103     T* m_ptr;
    104 };
    105 
    106 // For code size reasons, we do not want this inlined or templated.
    107 void sp_report_race();
    108 
    109 #undef COMPARE
    110 
    111 // ---------------------------------------------------------------------------
    112 // No user serviceable parts below here.
    113 
    114 template<typename T>
    115 sp<T>::sp(T* other)
    116         : m_ptr(other) {
    117     if (other)
    118         other->incStrong(this);
    119 }
    120 
    121 template<typename T>
    122 sp<T>::sp(const sp<T>& other)
    123         : m_ptr(other.m_ptr) {
    124     if (m_ptr)
    125         m_ptr->incStrong(this);
    126 }
    127 
    128 template<typename T>
    129 sp<T>::sp(sp<T>&& other)
    130         : m_ptr(other.m_ptr) {
    131     other.m_ptr = nullptr;
    132 }
    133 
    134 template<typename T> template<typename U>
    135 sp<T>::sp(U* other)
    136         : m_ptr(other) {
    137     if (other)
    138         (static_cast<T*>(other))->incStrong(this);
    139 }
    140 
    141 template<typename T> template<typename U>
    142 sp<T>::sp(const sp<U>& other)
    143         : m_ptr(other.m_ptr) {
    144     if (m_ptr)
    145         m_ptr->incStrong(this);
    146 }
    147 
    148 template<typename T> template<typename U>
    149 sp<T>::sp(sp<U>&& other)
    150         : m_ptr(other.m_ptr) {
    151     other.m_ptr = nullptr;
    152 }
    153 
    154 template<typename T>
    155 sp<T>::~sp() {
    156     if (m_ptr)
    157         m_ptr->decStrong(this);
    158 }
    159 
    160 template<typename T>
    161 sp<T>& sp<T>::operator =(const sp<T>& other) {
    162     // Force m_ptr to be read twice, to heuristically check for data races.
    163     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    164     T* otherPtr(other.m_ptr);
    165     if (otherPtr) otherPtr->incStrong(this);
    166     if (oldPtr) oldPtr->decStrong(this);
    167     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    168     m_ptr = otherPtr;
    169     return *this;
    170 }
    171 
    172 template<typename T>
    173 sp<T>& sp<T>::operator =(sp<T>&& other) {
    174     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    175     if (oldPtr) oldPtr->decStrong(this);
    176     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    177     m_ptr = other.m_ptr;
    178     other.m_ptr = nullptr;
    179     return *this;
    180 }
    181 
    182 template<typename T>
    183 sp<T>& sp<T>::operator =(T* other) {
    184     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    185     if (other) other->incStrong(this);
    186     if (oldPtr) oldPtr->decStrong(this);
    187     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    188     m_ptr = other;
    189     return *this;
    190 }
    191 
    192 template<typename T> template<typename U>
    193 sp<T>& sp<T>::operator =(const sp<U>& other) {
    194     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    195     T* otherPtr(other.m_ptr);
    196     if (otherPtr) otherPtr->incStrong(this);
    197     if (oldPtr) oldPtr->decStrong(this);
    198     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    199     m_ptr = otherPtr;
    200     return *this;
    201 }
    202 
    203 template<typename T> template<typename U>
    204 sp<T>& sp<T>::operator =(sp<U>&& other) {
    205     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    206     if (m_ptr) m_ptr->decStrong(this);
    207     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    208     m_ptr = other.m_ptr;
    209     other.m_ptr = nullptr;
    210     return *this;
    211 }
    212 
    213 template<typename T> template<typename U>
    214 sp<T>& sp<T>::operator =(U* other) {
    215     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    216     if (other) (static_cast<T*>(other))->incStrong(this);
    217     if (oldPtr) oldPtr->decStrong(this);
    218     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    219     m_ptr = other;
    220     return *this;
    221 }
    222 
    223 template<typename T>
    224 void sp<T>::force_set(T* other) {
    225     other->forceIncStrong(this);
    226     m_ptr = other;
    227 }
    228 
    229 template<typename T>
    230 void sp<T>::clear() {
    231     if (m_ptr) {
    232         m_ptr->decStrong(this);
    233         m_ptr = 0;
    234     }
    235 }
    236 
    237 template<typename T>
    238 void sp<T>::set_pointer(T* ptr) {
    239     m_ptr = ptr;
    240 }
    241 
    242 }; // namespace android
    243 
    244 // ---------------------------------------------------------------------------
    245 
    246 #endif // ANDROID_STRONG_POINTER_H
    247