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