• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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