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 ~SmartPtr()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 Ptr()77 T* Ptr() const { 78 return m_ptr; 79 } 80 constPtr()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. use()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. release()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