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// ---------------------------------------------------------------------------
27namespace android {
28
29class TextOutput;
30TextOutput& printStrongPointer(TextOutput& to, const void* val);
31
32template<typename T> class wp;
33
34// ---------------------------------------------------------------------------
35
36#define COMPARE(_op_)                                           \
37inline bool operator _op_ (const sp<T>& o) const {              \
38    return m_ptr _op_ o.m_ptr;                                  \
39}                                                               \
40inline bool operator _op_ (const T* o) const {                  \
41    return m_ptr _op_ o;                                        \
42}                                                               \
43template<typename U>                                            \
44inline bool operator _op_ (const sp<U>& o) const {              \
45    return m_ptr _op_ o.m_ptr;                                  \
46}                                                               \
47template<typename U>                                            \
48inline bool operator _op_ (const U* o) const {                  \
49    return m_ptr _op_ o;                                        \
50}                                                               \
51inline bool operator _op_ (const wp<T>& o) const {              \
52    return m_ptr _op_ o.m_ptr;                                  \
53}                                                               \
54template<typename U>                                            \
55inline bool operator _op_ (const wp<U>& o) const {              \
56    return m_ptr _op_ o.m_ptr;                                  \
57}
58
59// ---------------------------------------------------------------------------
60
61template <typename T>
62class sp
63{
64public:
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;  }
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;
107    void set_pointer(T* ptr);
108    T* m_ptr;
109};
110
111#undef COMPARE
112
113template <typename T>
114TextOutput& operator<<(TextOutput& to, const sp<T>& val);
115
116// ---------------------------------------------------------------------------
117// No user serviceable parts below here.
118
119template<typename T>
120sp<T>::sp(T* other)
121: m_ptr(other)
122  {
123    if (other) other->incStrong(this);
124  }
125
126template<typename T>
127sp<T>::sp(const sp<T>& other)
128: m_ptr(other.m_ptr)
129  {
130    if (m_ptr) m_ptr->incStrong(this);
131  }
132
133template<typename T> template<typename U>
134sp<T>::sp(U* other) : m_ptr(other)
135{
136    if (other) ((T*)other)->incStrong(this);
137}
138
139template<typename T> template<typename U>
140sp<T>::sp(const sp<U>& other)
141: m_ptr(other.m_ptr)
142  {
143    if (m_ptr) m_ptr->incStrong(this);
144  }
145
146template<typename T>
147sp<T>::~sp()
148{
149    if (m_ptr) m_ptr->decStrong(this);
150}
151
152template<typename T>
153sp<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
161template<typename T>
162sp<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
170template<typename T> template<typename U>
171sp<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
180template<typename T> template<typename U>
181sp<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
189template<typename T>
190void sp<T>::force_set(T* other)
191{
192    other->forceIncStrong(this);
193    m_ptr = other;
194}
195
196template<typename T>
197void sp<T>::clear()
198{
199    if (m_ptr) {
200        m_ptr->decStrong(this);
201        m_ptr = 0;
202    }
203}
204
205template<typename T>
206void sp<T>::set_pointer(T* ptr) {
207    m_ptr = ptr;
208}
209
210template <typename T>
211inline 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