1 /*
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 // ---------------------------------------------------------------------------
27 namespace android {
28 
29 template<typename T> class wp;
30 
31 // ---------------------------------------------------------------------------
32 
33 #define COMPARE(_op_)                                           \
34 inline bool operator _op_ (const sp<T>& o) const {              \
35     return m_ptr _op_ o.m_ptr;                                  \
36 }                                                               \
37 inline bool operator _op_ (const T* o) const {                  \
38     return m_ptr _op_ o;                                        \
39 }                                                               \
40 template<typename U>                                            \
41 inline bool operator _op_ (const sp<U>& o) const {              \
42     return m_ptr _op_ o.m_ptr;                                  \
43 }                                                               \
44 template<typename U>                                            \
45 inline bool operator _op_ (const U* o) const {                  \
46     return m_ptr _op_ o;                                        \
47 }                                                               \
48 inline bool operator _op_ (const wp<T>& o) const {              \
49     return m_ptr _op_ o.m_ptr;                                  \
50 }                                                               \
51 template<typename U>                                            \
52 inline bool operator _op_ (const wp<U>& o) const {              \
53     return m_ptr _op_ o.m_ptr;                                  \
54 }
55 
56 // ---------------------------------------------------------------------------
57 
58 template<typename T>
59 class sp {
60 public:
sp()61     inline sp() : m_ptr(0) { }
62 
63     sp(T* other);
64     sp(const sp<T>& other);
65     template<typename U> sp(U* other);
66     template<typename U> sp(const sp<U>& other);
67 
68     ~sp();
69 
70     // Assignment
71 
72     sp& operator = (T* other);
73     sp& operator = (const sp<T>& other);
74 
75     template<typename U> sp& operator = (const sp<U>& other);
76     template<typename U> sp& operator = (U* other);
77 
78     //! Special optimization for use by ProcessState (and nobody else).
79     void force_set(T* other);
80 
81     // Reset
82 
83     void clear();
84 
85     // Accessors
86 
87     inline  T&      operator* () const  { return *m_ptr; }
88     inline  T*      operator-> () const { return m_ptr;  }
get()89     inline  T*      get() const         { return m_ptr; }
90 
91     // Operators
92 
93     COMPARE(==)
94     COMPARE(!=)
95     COMPARE(>)
96     COMPARE(<)
97     COMPARE(<=)
98     COMPARE(>=)
99 
100 private:
101     template<typename Y> friend class sp;
102     template<typename Y> friend class wp;
103     void set_pointer(T* ptr);
104     T* m_ptr;
105 };
106 
107 #undef COMPARE
108 
109 // ---------------------------------------------------------------------------
110 // No user serviceable parts below here.
111 
112 template<typename T>
sp(T * other)113 sp<T>::sp(T* other)
114         : m_ptr(other) {
115     if (other)
116         other->incStrong(this);
117 }
118 
119 template<typename T>
sp(const sp<T> & other)120 sp<T>::sp(const sp<T>& other)
121         : m_ptr(other.m_ptr) {
122     if (m_ptr)
123         m_ptr->incStrong(this);
124 }
125 
126 template<typename T> template<typename U>
sp(U * other)127 sp<T>::sp(U* other)
128         : m_ptr(other) {
129     if (other)
130         ((T*) other)->incStrong(this);
131 }
132 
133 template<typename T> template<typename U>
sp(const sp<U> & other)134 sp<T>::sp(const sp<U>& other)
135         : m_ptr(other.m_ptr) {
136     if (m_ptr)
137         m_ptr->incStrong(this);
138 }
139 
140 template<typename T>
~sp()141 sp<T>::~sp() {
142     if (m_ptr)
143         m_ptr->decStrong(this);
144 }
145 
146 template<typename T>
147 sp<T>& sp<T>::operator =(const sp<T>& other) {
148     T* otherPtr(other.m_ptr);
149     if (otherPtr)
150         otherPtr->incStrong(this);
151     if (m_ptr)
152         m_ptr->decStrong(this);
153     m_ptr = otherPtr;
154     return *this;
155 }
156 
157 template<typename T>
158 sp<T>& sp<T>::operator =(T* other) {
159     if (other)
160         other->incStrong(this);
161     if (m_ptr)
162         m_ptr->decStrong(this);
163     m_ptr = other;
164     return *this;
165 }
166 
167 template<typename T> template<typename U>
168 sp<T>& sp<T>::operator =(const sp<U>& other) {
169     T* otherPtr(other.m_ptr);
170     if (otherPtr)
171         otherPtr->incStrong(this);
172     if (m_ptr)
173         m_ptr->decStrong(this);
174     m_ptr = otherPtr;
175     return *this;
176 }
177 
178 template<typename T> template<typename U>
179 sp<T>& sp<T>::operator =(U* other) {
180     if (other)
181         ((T*) other)->incStrong(this);
182     if (m_ptr)
183         m_ptr->decStrong(this);
184     m_ptr = other;
185     return *this;
186 }
187 
188 template<typename T>
force_set(T * other)189 void sp<T>::force_set(T* other) {
190     other->forceIncStrong(this);
191     m_ptr = other;
192 }
193 
194 template<typename T>
clear()195 void sp<T>::clear() {
196     if (m_ptr) {
197         m_ptr->decStrong(this);
198         m_ptr = 0;
199     }
200 }
201 
202 template<typename T>
set_pointer(T * ptr)203 void sp<T>::set_pointer(T* ptr) {
204     m_ptr = ptr;
205 }
206 
207 }; // namespace android
208 
209 // ---------------------------------------------------------------------------
210 
211 #endif // ANDROID_STRONG_POINTER_H
212