RefBase.h revision b798689749c64baba81f02e10cf2157c747d6b46
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_REF_BASE_H
18#define ANDROID_REF_BASE_H
19
20#include <cutils/atomic.h>
21#include <utils/TextOutput.h>
22
23#include <stdint.h>
24#include <sys/types.h>
25#include <stdlib.h>
26
27// ---------------------------------------------------------------------------
28namespace android {
29
30template<typename T> class wp;
31
32// ---------------------------------------------------------------------------
33
34#define COMPARE(_op_)                                           \
35inline bool operator _op_ (const sp<T>& o) const {              \
36    return m_ptr _op_ o.m_ptr;                                  \
37}                                                               \
38inline bool operator _op_ (const wp<T>& o) const {              \
39    return m_ptr _op_ o.m_ptr;                                  \
40}                                                               \
41inline bool operator _op_ (const T* o) const {                  \
42    return m_ptr _op_ o;                                        \
43}                                                               \
44template<typename U>                                            \
45inline bool operator _op_ (const sp<U>& o) const {              \
46    return m_ptr _op_ o.m_ptr;                                  \
47}                                                               \
48template<typename U>                                            \
49inline bool operator _op_ (const wp<U>& o) const {              \
50    return m_ptr _op_ o.m_ptr;                                  \
51}                                                               \
52template<typename U>                                            \
53inline bool operator _op_ (const U* o) const {                  \
54    return m_ptr _op_ o;                                        \
55}
56
57// ---------------------------------------------------------------------------
58
59class RefBase
60{
61public:
62            void            incStrong(const void* id) const;
63            void            decStrong(const void* id) const;
64
65            void            forceIncStrong(const void* id) const;
66
67            //! DEBUGGING ONLY: Get current strong ref count.
68            int32_t         getStrongCount() const;
69
70    class weakref_type
71    {
72    public:
73        RefBase*            refBase() const;
74
75        void                incWeak(const void* id);
76        void                decWeak(const void* id);
77
78        bool                attemptIncStrong(const void* id);
79
80        //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
81        bool                attemptIncWeak(const void* id);
82
83        //! DEBUGGING ONLY: Get current weak ref count.
84        int32_t             getWeakCount() const;
85
86        //! DEBUGGING ONLY: Print references held on object.
87        void                printRefs() const;
88
89        //! DEBUGGING ONLY: Enable tracking for this object.
90        // enable -- enable/disable tracking
91        // retain -- when tracking is enable, if true, then we save a stack trace
92        //           for each reference and dereference; when retain == false, we
93        //           match up references and dereferences and keep only the
94        //           outstanding ones.
95
96        void                trackMe(bool enable, bool retain);
97    };
98
99            weakref_type*   createWeak(const void* id) const;
100
101            weakref_type*   getWeakRefs() const;
102
103            //! DEBUGGING ONLY: Print references held on object.
104    inline  void            printRefs() const { getWeakRefs()->printRefs(); }
105
106            //! DEBUGGING ONLY: Enable tracking of object.
107    inline  void            trackMe(bool enable, bool retain)
108    {
109        getWeakRefs()->trackMe(enable, retain);
110    }
111
112protected:
113                            RefBase();
114    virtual                 ~RefBase();
115
116    //! Flags for extendObjectLifetime()
117    enum {
118        OBJECT_LIFETIME_WEAK    = 0x0001,
119        OBJECT_LIFETIME_FOREVER = 0x0003
120    };
121
122            void            extendObjectLifetime(int32_t mode);
123
124    //! Flags for onIncStrongAttempted()
125    enum {
126        FIRST_INC_STRONG = 0x0001
127    };
128
129    virtual void            onFirstRef();
130    virtual void            onLastStrongRef(const void* id);
131    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
132    virtual void            onLastWeakRef(const void* id);
133
134private:
135    friend class weakref_type;
136    class weakref_impl;
137
138                            RefBase(const RefBase& o);
139            RefBase&        operator=(const RefBase& o);
140
141        weakref_impl* const mRefs;
142};
143
144// ---------------------------------------------------------------------------
145
146template <class T>
147class LightRefBase
148{
149public:
150    inline LightRefBase() : mCount(0) { }
151    inline void incStrong(const void* id) const {
152        android_atomic_inc(&mCount);
153    }
154    inline void decStrong(const void* id) const {
155        if (android_atomic_dec(&mCount) == 1) {
156            delete static_cast<const T*>(this);
157        }
158    }
159
160protected:
161    inline ~LightRefBase() { }
162
163private:
164    mutable volatile int32_t mCount;
165};
166
167// ---------------------------------------------------------------------------
168
169template <typename T>
170class sp
171{
172public:
173    typedef typename RefBase::weakref_type weakref_type;
174
175    inline sp() : m_ptr(0) { }
176
177    sp(T* other);
178    sp(const sp<T>& other);
179    template<typename U> sp(U* other);
180    template<typename U> sp(const sp<U>& other);
181
182    ~sp();
183
184    // Assignment
185
186    sp& operator = (T* other);
187    sp& operator = (const sp<T>& other);
188
189    template<typename U> sp& operator = (const sp<U>& other);
190    template<typename U> sp& operator = (U* other);
191
192    //! Special optimization for use by ProcessState (and nobody else).
193    void force_set(T* other);
194
195    // Reset
196
197    void clear();
198
199    // Accessors
200
201    inline  T&      operator* () const  { return *m_ptr; }
202    inline  T*      operator-> () const { return m_ptr;  }
203    inline  T*      get() const         { return m_ptr; }
204
205    // Operators
206
207    COMPARE(==)
208    COMPARE(!=)
209    COMPARE(>)
210    COMPARE(<)
211    COMPARE(<=)
212    COMPARE(>=)
213
214private:
215    template<typename Y> friend class sp;
216    template<typename Y> friend class wp;
217
218    // Optimization for wp::promote().
219    sp(T* p, weakref_type* refs);
220
221    T*              m_ptr;
222};
223
224template <typename T>
225TextOutput& operator<<(TextOutput& to, const sp<T>& val);
226
227// ---------------------------------------------------------------------------
228
229template <typename T>
230class wp
231{
232public:
233    typedef typename RefBase::weakref_type weakref_type;
234
235    inline wp() : m_ptr(0) { }
236
237    wp(T* other);
238    wp(const wp<T>& other);
239    wp(const sp<T>& other);
240    template<typename U> wp(U* other);
241    template<typename U> wp(const sp<U>& other);
242    template<typename U> wp(const wp<U>& other);
243
244    ~wp();
245
246    // Assignment
247
248    wp& operator = (T* other);
249    wp& operator = (const wp<T>& other);
250    wp& operator = (const sp<T>& other);
251
252    template<typename U> wp& operator = (U* other);
253    template<typename U> wp& operator = (const wp<U>& other);
254    template<typename U> wp& operator = (const sp<U>& other);
255
256    void set_object_and_refs(T* other, weakref_type* refs);
257
258    // promotion to sp
259
260    sp<T> promote() const;
261
262    // Reset
263
264    void clear();
265
266    // Accessors
267
268    inline  weakref_type* get_refs() const { return m_refs; }
269
270    inline  T* unsafe_get() const { return m_ptr; }
271
272    // Operators
273
274    COMPARE(==)
275    COMPARE(!=)
276    COMPARE(>)
277    COMPARE(<)
278    COMPARE(<=)
279    COMPARE(>=)
280
281private:
282    template<typename Y> friend class sp;
283    template<typename Y> friend class wp;
284
285    T*              m_ptr;
286    weakref_type*   m_refs;
287};
288
289template <typename T>
290TextOutput& operator<<(TextOutput& to, const wp<T>& val);
291
292#undef COMPARE
293
294// ---------------------------------------------------------------------------
295// No user serviceable parts below here.
296
297template<typename T>
298sp<T>::sp(T* other)
299    : m_ptr(other)
300{
301    if (other) other->incStrong(this);
302}
303
304template<typename T>
305sp<T>::sp(const sp<T>& other)
306    : m_ptr(other.m_ptr)
307{
308    if (m_ptr) m_ptr->incStrong(this);
309}
310
311template<typename T> template<typename U>
312sp<T>::sp(U* other) : m_ptr(other)
313{
314    if (other) other->incStrong(this);
315}
316
317template<typename T> template<typename U>
318sp<T>::sp(const sp<U>& other)
319    : m_ptr(other.m_ptr)
320{
321    if (m_ptr) m_ptr->incStrong(this);
322}
323
324template<typename T>
325sp<T>::~sp()
326{
327    if (m_ptr) m_ptr->decStrong(this);
328}
329
330template<typename T>
331sp<T>& sp<T>::operator = (const sp<T>& other) {
332    if (other.m_ptr) other.m_ptr->incStrong(this);
333    if (m_ptr) m_ptr->decStrong(this);
334    m_ptr = other.m_ptr;
335    return *this;
336}
337
338template<typename T>
339sp<T>& sp<T>::operator = (T* other)
340{
341    if (other) other->incStrong(this);
342    if (m_ptr) m_ptr->decStrong(this);
343    m_ptr = other;
344    return *this;
345}
346
347template<typename T> template<typename U>
348sp<T>& sp<T>::operator = (const sp<U>& other)
349{
350    if (other.m_ptr) other.m_ptr->incStrong(this);
351    if (m_ptr) m_ptr->decStrong(this);
352    m_ptr = other.m_ptr;
353    return *this;
354}
355
356template<typename T> template<typename U>
357sp<T>& sp<T>::operator = (U* other)
358{
359    if (other) other->incStrong(this);
360    if (m_ptr) m_ptr->decStrong(this);
361    m_ptr = other;
362    return *this;
363}
364
365template<typename T>
366void sp<T>::force_set(T* other)
367{
368    other->forceIncStrong(this);
369    m_ptr = other;
370}
371
372template<typename T>
373void sp<T>::clear()
374{
375    if (m_ptr) {
376        m_ptr->decStrong(this);
377        m_ptr = 0;
378    }
379}
380
381template<typename T>
382sp<T>::sp(T* p, weakref_type* refs)
383    : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
384{
385}
386
387template <typename T>
388inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
389{
390    to << "sp<>(" << val.get() << ")";
391    return to;
392}
393
394// ---------------------------------------------------------------------------
395
396template<typename T>
397wp<T>::wp(T* other)
398    : m_ptr(other)
399{
400    if (other) m_refs = other->createWeak(this);
401}
402
403template<typename T>
404wp<T>::wp(const wp<T>& other)
405    : m_ptr(other.m_ptr), m_refs(other.m_refs)
406{
407    if (m_ptr) m_refs->incWeak(this);
408}
409
410template<typename T>
411wp<T>::wp(const sp<T>& other)
412    : m_ptr(other.m_ptr)
413{
414    if (m_ptr) {
415        m_refs = m_ptr->createWeak(this);
416    }
417}
418
419template<typename T> template<typename U>
420wp<T>::wp(U* other)
421    : m_ptr(other)
422{
423    if (other) m_refs = other->createWeak(this);
424}
425
426template<typename T> template<typename U>
427wp<T>::wp(const wp<U>& other)
428    : m_ptr(other.m_ptr)
429{
430    if (m_ptr) {
431        m_refs = other.m_refs;
432        m_refs->incWeak(this);
433    }
434}
435
436template<typename T> template<typename U>
437wp<T>::wp(const sp<U>& other)
438    : m_ptr(other.m_ptr)
439{
440    if (m_ptr) {
441        m_refs = m_ptr->createWeak(this);
442    }
443}
444
445template<typename T>
446wp<T>::~wp()
447{
448    if (m_ptr) m_refs->decWeak(this);
449}
450
451template<typename T>
452wp<T>& wp<T>::operator = (T* other)
453{
454    weakref_type* newRefs =
455        other ? other->createWeak(this) : 0;
456    if (m_ptr) m_refs->decWeak(this);
457    m_ptr = other;
458    m_refs = newRefs;
459    return *this;
460}
461
462template<typename T>
463wp<T>& wp<T>::operator = (const wp<T>& other)
464{
465    if (other.m_ptr) other.m_refs->incWeak(this);
466    if (m_ptr) m_refs->decWeak(this);
467    m_ptr = other.m_ptr;
468    m_refs = other.m_refs;
469    return *this;
470}
471
472template<typename T>
473wp<T>& wp<T>::operator = (const sp<T>& other)
474{
475    weakref_type* newRefs =
476        other != NULL ? other->createWeak(this) : 0;
477    if (m_ptr) m_refs->decWeak(this);
478    m_ptr = other.get();
479    m_refs = newRefs;
480    return *this;
481}
482
483template<typename T> template<typename U>
484wp<T>& wp<T>::operator = (U* other)
485{
486    weakref_type* newRefs =
487        other ? other->createWeak(this) : 0;
488    if (m_ptr) m_refs->decWeak(this);
489    m_ptr = other;
490    m_refs = newRefs;
491    return *this;
492}
493
494template<typename T> template<typename U>
495wp<T>& wp<T>::operator = (const wp<U>& other)
496{
497    if (other.m_ptr) other.m_refs->incWeak(this);
498    if (m_ptr) m_refs->decWeak(this);
499    m_ptr = other.m_ptr;
500    m_refs = other.m_refs;
501    return *this;
502}
503
504template<typename T> template<typename U>
505wp<T>& wp<T>::operator = (const sp<U>& other)
506{
507    weakref_type* newRefs =
508        other != NULL ? other->createWeak(this) : 0;
509    if (m_ptr) m_refs->decWeak(this);
510    m_ptr = other.get();
511    m_refs = newRefs;
512    return *this;
513}
514
515template<typename T>
516void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
517{
518    if (other) refs->incWeak(this);
519    if (m_ptr) m_refs->decWeak(this);
520    m_ptr = other;
521    m_refs = refs;
522}
523
524template<typename T>
525sp<T> wp<T>::promote() const
526{
527    return sp<T>(m_ptr, m_refs);
528}
529
530template<typename T>
531void wp<T>::clear()
532{
533    if (m_ptr) {
534        m_refs->decWeak(this);
535        m_ptr = 0;
536    }
537}
538
539template <typename T>
540inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
541{
542    to << "wp<>(" << val.unsafe_get() << ")";
543    return to;
544}
545
546}; // namespace android
547
548// ---------------------------------------------------------------------------
549
550#endif // ANDROID_REF_BASE_H
551