Home | History | Annotate | Download | only in OpenglCodecCommon
      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     operator void*() const {
     95         return (void *)m_ptr;
     96     }
     97 
     98     // This gives STL lists something to compare.
     99     bool operator <(const SmartPtr<T>& t1) const {
    100         return m_ptr < t1.m_ptr;
    101     }
    102 
    103     SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs)
    104     {
    105         if (m_ptr == rhs.m_ptr)
    106             return *this;
    107 
    108         if (m_lock) mutex_lock(m_lock);
    109         release();
    110         m_pRefCount = rhs.m_pRefCount;
    111         m_ptr       = rhs.m_ptr;
    112         use();
    113         if (m_lock) mutex_unlock(m_lock);
    114 
    115         return *this;
    116     }
    117 
    118     SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs)
    119     {
    120         if (m_ptr == rhs.m_ptr)
    121             return *this;
    122 
    123         if (m_lock) mutex_lock(m_lock);
    124         release();
    125         if (rhs.m_lock) mutex_lock(rhs.m_lock);
    126         m_pRefCount = rhs.m_pRefCount;
    127         m_ptr       = rhs.m_ptr;
    128         use();
    129         if (rhs.m_lock) mutex_unlock(rhs.m_lock);
    130         if (m_lock) mutex_unlock(m_lock);
    131 
    132         return *this;
    133     }
    134 
    135 private:
    136     int32_t  *m_pRefCount;
    137     mutex_t  *m_lock;
    138     T* m_ptr;
    139 
    140     // Increment the reference count on this pointer by 1.
    141     int use() {
    142         if (!m_pRefCount) return 0;
    143         return android_atomic_inc(m_pRefCount) + 1;
    144     }
    145 
    146     // Decrement the reference count on the pointer by 1.
    147     // If the reference count goes to (or below) 0, the pointer is deleted.
    148     int release() {
    149         if (!m_pRefCount) return 0;
    150 
    151         int iVal = android_atomic_dec(m_pRefCount);
    152         if (iVal > 1)
    153             return iVal - 1;
    154 
    155         delete m_pRefCount;
    156         m_pRefCount = NULL;
    157 
    158         if (m_ptr) {
    159             delete m_ptr;
    160             m_ptr = NULL;
    161         }
    162         return 0;
    163     }
    164 
    165 };
    166 
    167 #endif // of  __SMART_PTR_H
    168