blob: 3d821c87d3789c3a0be7c49444eed2de6e834511 [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
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
Elliott Hughese8052e42018-07-13 13:06:08 -070019#include <PortableMutex.h>
20
keunyoungb85b2752013-03-08 12:28:03 -080021#include <cutils/atomic.h>
22
23template <class T, bool threadSafe = false>
24class SmartPtr
25{
26public:
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
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
78 T* Ptr() const {
79 return m_ptr;
80 }
81
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
136private:
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.
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.
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