blob: c2f7722220bc3cc6850cf1a3a7383ffa0b521c30 [file] [log] [blame]
Mathias Agopianb26ea8b2011-02-16 20:23:43 -08001/*
2 * Copyright (C) 2005 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
17#ifndef ANDROID_STRONG_POINTER_H
18#define ANDROID_STRONG_POINTER_H
19
20#include <cutils/atomic.h>
21
22#include <stdint.h>
23#include <sys/types.h>
24#include <stdlib.h>
25
26// ---------------------------------------------------------------------------
27namespace android {
28
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080029template<typename T> class wp;
30
31// ---------------------------------------------------------------------------
32
33#define COMPARE(_op_) \
34inline bool operator _op_ (const sp<T>& o) const { \
35 return m_ptr _op_ o.m_ptr; \
36} \
37inline bool operator _op_ (const T* o) const { \
38 return m_ptr _op_ o; \
39} \
40template<typename U> \
41inline bool operator _op_ (const sp<U>& o) const { \
42 return m_ptr _op_ o.m_ptr; \
43} \
44template<typename U> \
45inline bool operator _op_ (const U* o) const { \
46 return m_ptr _op_ o; \
47} \
48inline bool operator _op_ (const wp<T>& o) const { \
49 return m_ptr _op_ o.m_ptr; \
50} \
51template<typename U> \
52inline bool operator _op_ (const wp<U>& o) const { \
53 return m_ptr _op_ o.m_ptr; \
54}
55
56// ---------------------------------------------------------------------------
57
Mathias Agopian8db925f2013-05-09 13:04:32 -070058template<typename T>
59class sp {
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080060public:
61 inline sp() : m_ptr(0) { }
62
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -070063 sp(T* other); // NOLINT(implicit)
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080064 sp(const sp<T>& other);
John Reckd69089a2015-10-28 15:36:33 -070065 sp(sp<T>&& other);
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -070066 template<typename U> sp(U* other); // NOLINT(implicit)
67 template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
68 template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080069
70 ~sp();
71
72 // Assignment
73
74 sp& operator = (T* other);
75 sp& operator = (const sp<T>& other);
John Reckd69089a2015-10-28 15:36:33 -070076 sp& operator = (sp<T>&& other);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080077
78 template<typename U> sp& operator = (const sp<U>& other);
John Reckd69089a2015-10-28 15:36:33 -070079 template<typename U> sp& operator = (sp<U>&& other);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -080080 template<typename U> sp& operator = (U* other);
81
82 //! Special optimization for use by ProcessState (and nobody else).
83 void force_set(T* other);
84
85 // Reset
86
87 void clear();
88
89 // Accessors
90
91 inline T& operator* () const { return *m_ptr; }
92 inline T* operator-> () const { return m_ptr; }
93 inline T* get() const { return m_ptr; }
94
95 // Operators
96
97 COMPARE(==)
98 COMPARE(!=)
99 COMPARE(>)
100 COMPARE(<)
101 COMPARE(<=)
102 COMPARE(>=)
103
104private:
105 template<typename Y> friend class sp;
106 template<typename Y> friend class wp;
Mathias Agopian3e0f8752011-02-24 18:12:34 -0800107 void set_pointer(T* ptr);
108 T* m_ptr;
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800109};
110
Hans Boehm7f0b2602017-03-15 11:01:03 -0700111// For code size reasons, we do not want this inlined or templated.
112void sp_report_race();
113
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800114#undef COMPARE
115
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800116// ---------------------------------------------------------------------------
117// No user serviceable parts below here.
118
119template<typename T>
120sp<T>::sp(T* other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700121 : m_ptr(other) {
122 if (other)
123 other->incStrong(this);
124}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800125
126template<typename T>
127sp<T>::sp(const sp<T>& other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700128 : m_ptr(other.m_ptr) {
129 if (m_ptr)
130 m_ptr->incStrong(this);
131}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800132
John Reckd69089a2015-10-28 15:36:33 -0700133template<typename T>
134sp<T>::sp(sp<T>&& other)
135 : m_ptr(other.m_ptr) {
136 other.m_ptr = nullptr;
137}
138
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800139template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700140sp<T>::sp(U* other)
141 : m_ptr(other) {
142 if (other)
Colin Cross17b5b822016-09-15 18:15:37 -0700143 (static_cast<T*>(other))->incStrong(this);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800144}
145
146template<typename T> template<typename U>
147sp<T>::sp(const sp<U>& other)
Mathias Agopian8db925f2013-05-09 13:04:32 -0700148 : m_ptr(other.m_ptr) {
149 if (m_ptr)
150 m_ptr->incStrong(this);
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800151}
152
John Reckd69089a2015-10-28 15:36:33 -0700153template<typename T> template<typename U>
154sp<T>::sp(sp<U>&& other)
155 : m_ptr(other.m_ptr) {
156 other.m_ptr = nullptr;
157}
158
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800159template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700160sp<T>::~sp() {
161 if (m_ptr)
162 m_ptr->decStrong(this);
163}
164
165template<typename T>
166sp<T>& sp<T>::operator =(const sp<T>& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700167 // Force m_ptr to be read twice, to heuristically check for data races.
168 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800169 T* otherPtr(other.m_ptr);
Hans Boehm7f0b2602017-03-15 11:01:03 -0700170 if (otherPtr) otherPtr->incStrong(this);
171 if (oldPtr) oldPtr->decStrong(this);
172 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800173 m_ptr = otherPtr;
174 return *this;
175}
176
177template<typename T>
John Reckd69089a2015-10-28 15:36:33 -0700178sp<T>& sp<T>::operator =(sp<T>&& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700179 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
180 if (oldPtr) oldPtr->decStrong(this);
181 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
John Reckd69089a2015-10-28 15:36:33 -0700182 m_ptr = other.m_ptr;
183 other.m_ptr = nullptr;
184 return *this;
185}
186
187template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700188sp<T>& sp<T>::operator =(T* other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700189 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
190 if (other) other->incStrong(this);
191 if (oldPtr) oldPtr->decStrong(this);
192 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800193 m_ptr = other;
194 return *this;
195}
196
197template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700198sp<T>& sp<T>::operator =(const sp<U>& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700199 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
Mathias Agopian7332f802011-02-25 16:11:44 -0800200 T* otherPtr(other.m_ptr);
Hans Boehm7f0b2602017-03-15 11:01:03 -0700201 if (otherPtr) otherPtr->incStrong(this);
202 if (oldPtr) oldPtr->decStrong(this);
203 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800204 m_ptr = otherPtr;
205 return *this;
206}
207
208template<typename T> template<typename U>
John Reckd69089a2015-10-28 15:36:33 -0700209sp<T>& sp<T>::operator =(sp<U>&& other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700210 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
211 if (m_ptr) m_ptr->decStrong(this);
212 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
John Reckd69089a2015-10-28 15:36:33 -0700213 m_ptr = other.m_ptr;
214 other.m_ptr = nullptr;
215 return *this;
216}
217
218template<typename T> template<typename U>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700219sp<T>& sp<T>::operator =(U* other) {
Hans Boehm7f0b2602017-03-15 11:01:03 -0700220 T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
221 if (other) (static_cast<T*>(other))->incStrong(this);
222 if (oldPtr) oldPtr->decStrong(this);
223 if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800224 m_ptr = other;
225 return *this;
226}
227
Mathias Agopian8db925f2013-05-09 13:04:32 -0700228template<typename T>
229void sp<T>::force_set(T* other) {
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800230 other->forceIncStrong(this);
231 m_ptr = other;
232}
233
234template<typename T>
Mathias Agopian8db925f2013-05-09 13:04:32 -0700235void sp<T>::clear() {
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800236 if (m_ptr) {
237 m_ptr->decStrong(this);
238 m_ptr = 0;
239 }
240}
241
242template<typename T>
Mathias Agopian3e0f8752011-02-24 18:12:34 -0800243void sp<T>::set_pointer(T* ptr) {
244 m_ptr = ptr;
245}
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800246
Mathias Agopianb26ea8b2011-02-16 20:23:43 -0800247}; // namespace android
248
249// ---------------------------------------------------------------------------
250
251#endif // ANDROID_STRONG_POINTER_H