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 22template <class T, bool threadSafe = false> 23class SmartPtr 24{ 25public: 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 135private: 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