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