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// ---------------------------------------------------------------------------
27namespace android {
28
29template<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
58template<typename T>
59class sp {
60public:
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;  }
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
100private:
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
112template<typename T>
113sp<T>::sp(T* other)
114        : m_ptr(other) {
115    if (other)
116        other->incStrong(this);
117}
118
119template<typename T>
120sp<T>::sp(const sp<T>& other)
121        : m_ptr(other.m_ptr) {
122    if (m_ptr)
123        m_ptr->incStrong(this);
124}
125
126template<typename T> template<typename U>
127sp<T>::sp(U* other)
128        : m_ptr(other) {
129    if (other)
130        ((T*) other)->incStrong(this);
131}
132
133template<typename T> template<typename U>
134sp<T>::sp(const sp<U>& other)
135        : m_ptr(other.m_ptr) {
136    if (m_ptr)
137        m_ptr->incStrong(this);
138}
139
140template<typename T>
141sp<T>::~sp() {
142    if (m_ptr)
143        m_ptr->decStrong(this);
144}
145
146template<typename T>
147sp<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
157template<typename T>
158sp<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
167template<typename T> template<typename U>
168sp<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
178template<typename T> template<typename U>
179sp<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
188template<typename T>
189void sp<T>::force_set(T* other) {
190    other->forceIncStrong(this);
191    m_ptr = other;
192}
193
194template<typename T>
195void sp<T>::clear() {
196    if (m_ptr) {
197        m_ptr->decStrong(this);
198        m_ptr = 0;
199    }
200}
201
202template<typename T>
203void 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