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