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