Home | History | Annotate | Download | only in GLcommon
      1 /*
      2 * Copyright (C) 2011 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 #ifndef __SMART_PTR_H
     17 #define __SMART_PTR_H
     18 
     19 #include <cutils/threads.h>
     20 #include <cutils/atomic.h>
     21 
     22 template <class T, bool threadSafe = false>
     23 class SmartPtr
     24 {
     25 public:
     26     explicit SmartPtr(T* ptr = (T*)NULL) {
     27         if (threadSafe) {
     28             m_lock = new mutex_t;
     29             mutex_init(m_lock);
     30         }
     31         else m_lock = NULL;
     32 
     33         m_ptr = ptr;
     34         if (ptr)
     35            m_pRefCount = new int32_t(1);
     36         else
     37            m_pRefCount = NULL;
     38     }
     39 
     40     SmartPtr<T,threadSafe>(const SmartPtr<T,false>& rhs) {
     41         if (threadSafe) {
     42             m_lock = new mutex_t;
     43             mutex_init(m_lock);
     44         }
     45         else m_lock = NULL;
     46 
     47         m_pRefCount = rhs.m_pRefCount;
     48         m_ptr       = rhs.m_ptr;
     49         use();
     50     }
     51 
     52     SmartPtr<T,threadSafe>(SmartPtr<T,true>& rhs) {
     53         if (threadSafe) {
     54             m_lock = new mutex_t;
     55             mutex_init(m_lock);
     56         }
     57         else m_lock = NULL;
     58 
     59         if (rhs.m_lock) mutex_lock(rhs.m_lock);
     60         m_pRefCount = rhs.m_pRefCount;
     61         m_ptr       = rhs.m_ptr;
     62         use();
     63         if (rhs.m_lock) mutex_unlock(rhs.m_lock);
     64     }
     65 
     66     ~SmartPtr() {
     67         if (m_lock) mutex_lock(m_lock);
     68         release();
     69         if (m_lock)
     70         {
     71             mutex_unlock(m_lock);
     72             mutex_destroy(m_lock);
     73             delete m_lock;
     74         }
     75     }
     76 
     77     T* Ptr() const {
     78         return m_ptr;
     79     }
     80 
     81     const T* constPtr() const
     82     {
     83         return m_ptr;
     84     }
     85 
     86     T* operator->() const {
     87         return m_ptr;
     88     }
     89 
     90     T& operator*() const {
     91         return *m_ptr;
     92     }
     93 
     94     // This gives STL lists something to compare.
     95     bool operator <(const SmartPtr<T>& t1) const {
     96         return m_ptr < t1.m_ptr;
     97     }
     98 
     99     SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs)
    100     {
    101         if (m_ptr == rhs.m_ptr)
    102             return *this;
    103 
    104         if (m_lock) mutex_lock(m_lock);
    105         release();
    106         m_pRefCount = rhs.m_pRefCount;
    107         m_ptr       = rhs.m_ptr;
    108         use();
    109         if (m_lock) mutex_unlock(m_lock);
    110 
    111         return *this;
    112     }
    113 
    114     SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs)
    115     {
    116         if (m_ptr == rhs.m_ptr)
    117             return *this;
    118 
    119         if (m_lock) mutex_lock(m_lock);
    120         release();
    121         if (rhs.m_lock) mutex_lock(rhs.m_lock);
    122         m_pRefCount = rhs.m_pRefCount;
    123         m_ptr       = rhs.m_ptr;
    124         use();
    125         if (rhs.m_lock) mutex_unlock(rhs.m_lock);
    126         if (m_lock) mutex_unlock(m_lock);
    127 
    128         return *this;
    129     }
    130 
    131 private:
    132     int32_t  *m_pRefCount;
    133     mutex_t  *m_lock;
    134     T* m_ptr;
    135 
    136     // Increment the reference count on this pointer by 1.
    137     int use() {
    138         if (!m_pRefCount) return 0;
    139         return android_atomic_inc(m_pRefCount) + 1;
    140     }
    141 
    142     // Decrement the reference count on the pointer by 1.
    143     // If the reference count goes to (or below) 0, the pointer is deleted.
    144     int release() {
    145         if (!m_pRefCount) return 0;
    146 
    147         int iVal = android_atomic_dec(m_pRefCount);
    148         if (iVal > 1)
    149             return iVal - 1;
    150 
    151         delete m_pRefCount;
    152         m_pRefCount = NULL;
    153 
    154         if (m_ptr) {
    155             delete m_ptr;
    156             m_ptr = NULL;
    157         }
    158         return 0;
    159     }
    160 
    161 };
    162 
    163 #endif // of  __SMART_PTR_H
    164