SkRefCnt.h revision 6d2533ebd2ad5168d08f5a83e681881c0d533949
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkRefCnt_DEFINED
11#define SkRefCnt_DEFINED
12
13#include "SkThread.h"
14#include "SkInstCnt.h"
15#include "SkTemplates.h"
16
17#ifdef SK_REF_CNT_BASE_INCLUDE
18#include SK_REF_CNT_BASE_INCLUDE
19#else
20/** \class SkRefCntBase
21
22    Default implementation of SkRefCntBase. The base class' contract is to
23    provide an implementation of aboutToRef. Embedders of skia can specify
24    an alternate implementation by setting SK_REF_CNT_BASE_INCLUDE. This is
25    useful for adding debug run-time checks to enforce certain usage patterns.
26*/
27class SK_API SkRefCntBase {
28public:
29    void aboutToRef() const {}
30};
31#endif
32
33/** \class SkRefCnt
34
35    SkRefCnt is the base class for objects that may be shared by multiple
36    objects. When an existing owner wants to share a reference, it calls ref().
37    When an owner wants to release its reference, it calls unref(). When the
38    shared object's reference count goes to zero as the result of an unref()
39    call, its (virtual) destructor is called. It is an error for the
40    destructor to be called explicitly (or via the object going out of scope on
41    the stack or calling delete) if getRefCnt() > 1.
42*/
43class SK_API SkRefCnt : public SkRefCntBase {
44public:
45    SK_DECLARE_INST_COUNT_ROOT(SkRefCnt)
46
47    /** Default construct, initializing the reference count to 1.
48    */
49    SkRefCnt() : fRefCnt(1) {}
50
51    /** Destruct, asserting that the reference count is 1.
52    */
53    virtual ~SkRefCnt() {
54#ifdef SK_DEBUG
55        SkASSERT(fRefCnt == 1);
56        fRefCnt = 0;    // illegal value, to catch us if we reuse after delete
57#endif
58    }
59
60    /** Return the reference count. Use only for debugging. */
61    int32_t getRefCnt() const { return fRefCnt; }
62
63    /** Returns true if the caller is the only owner.
64     *  Ensures that all previous owner's actions are complete.
65     */
66    bool unique() const {
67        bool const unique = (1 == fRefCnt);
68        if (unique) {
69            // Aquire barrier (L/SL), if not provided by load of fRefCnt.
70            // Prevents user's 'unique' code from happening before decrements.
71            //TODO: issue the barrier.
72        }
73        return unique;
74    }
75
76    /** Increment the reference count. Must be balanced by a call to unref().
77    */
78    void ref() const {
79        SkASSERT(fRefCnt > 0);
80        this->INHERITED::aboutToRef();
81        sk_atomic_inc(&fRefCnt);  // No barrier required.
82    }
83
84    /** Decrement the reference count. If the reference count is 1 before the
85        decrement, then delete the object. Note that if this is the case, then
86        the object needs to have been allocated via new, and not on the stack.
87    */
88    void unref() const {
89        SkASSERT(fRefCnt > 0);
90        // Release barrier (SL/S), if not provided below.
91        if (sk_atomic_dec(&fRefCnt) == 1) {
92            // Aquire barrier (L/SL), if not provided above.
93            // Prevents code in dispose from happening before the decrement.
94            sk_membar_aquire__after_atomic_dec();
95            internal_dispose();
96        }
97    }
98
99#ifdef SK_DEBUG
100    void validate() const {
101        SkASSERT(fRefCnt > 0);
102    }
103#endif
104
105    /**
106     * Alias for unref(), for compatibility with WTF::RefPtr.
107     */
108    void deref() { this->unref(); }
109
110protected:
111    /**
112     *  Allow subclasses to call this if they've overridden internal_dispose
113     *  so they can reset fRefCnt before the destructor is called. Should only
114     *  be called right before calling through to inherited internal_dispose()
115     *  or before calling the destructor.
116     */
117    void internal_dispose_restore_refcnt_to_1() const {
118#ifdef SK_DEBUG
119        SkASSERT(0 == fRefCnt);
120        fRefCnt = 1;
121#endif
122    }
123
124private:
125    /**
126     *  Make SkRefCnt non-copyable.
127     */
128    SkRefCnt(const SkRefCnt&);
129    SkRefCnt& operator=(const SkRefCnt&);
130
131    /**
132     *  Called when the ref count goes to 0.
133     */
134    virtual void internal_dispose() const {
135        this->internal_dispose_restore_refcnt_to_1();
136        SkDELETE(this);
137    }
138
139    // The following friends are those which override internal_dispose()
140    // and conditionally call SkRefCnt::internal_dispose().
141    friend class GrTexture;
142    friend class SkWeakRefCnt;
143
144    mutable int32_t fRefCnt;
145
146    typedef SkRefCntBase INHERITED;
147};
148
149///////////////////////////////////////////////////////////////////////////////
150
151/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
152    null in on each side of the assignment, and ensuring that ref() is called
153    before unref(), in case the two pointers point to the same object.
154 */
155#define SkRefCnt_SafeAssign(dst, src)   \
156    do {                                \
157        if (src) src->ref();            \
158        if (dst) dst->unref();          \
159        dst = src;                      \
160    } while (0)
161
162
163/** Call obj->ref() and return obj. The obj must not be NULL.
164 */
165template <typename T> static inline T* SkRef(T* obj) {
166    SkASSERT(obj);
167    obj->ref();
168    return obj;
169}
170
171/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
172 */
173template <typename T> static inline T* SkSafeRef(T* obj) {
174    if (obj) {
175        obj->ref();
176    }
177    return obj;
178}
179
180/** Check if the argument is non-null, and if so, call obj->unref()
181 */
182template <typename T> static inline void SkSafeUnref(T* obj) {
183    if (obj) {
184        obj->unref();
185    }
186}
187
188template<typename T> static inline void SkSafeSetNull(T*& obj) {
189    if (NULL != obj) {
190        obj->unref();
191        obj = NULL;
192    }
193}
194
195///////////////////////////////////////////////////////////////////////////////
196
197/**
198 *  Utility class that simply unref's its argument in the destructor.
199 */
200template <typename T> class SkAutoTUnref : SkNoncopyable {
201public:
202    explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
203    ~SkAutoTUnref() { SkSafeUnref(fObj); }
204
205    T* get() const { return fObj; }
206
207    T* reset(T* obj) {
208        SkSafeUnref(fObj);
209        fObj = obj;
210        return obj;
211    }
212
213    void swap(SkAutoTUnref* other) {
214        T* tmp = fObj;
215        fObj = other->fObj;
216        other->fObj = tmp;
217    }
218
219    /**
220     *  Return the hosted object (which may be null), transferring ownership.
221     *  The reference count is not modified, and the internal ptr is set to NULL
222     *  so unref() will not be called in our destructor. A subsequent call to
223     *  detach() will do nothing and return null.
224     */
225    T* detach() {
226        T* obj = fObj;
227        fObj = NULL;
228        return obj;
229    }
230
231    /**
232     *  BlockRef<B> is a type which inherits from B, cannot be created,
233     *  cannot be deleted, and makes ref and unref private.
234     */
235    template<typename B> class BlockRef : public B {
236    private:
237        BlockRef();
238        ~BlockRef();
239        void ref() const;
240        void unref() const;
241    };
242
243    /** If T is const, the type returned from operator-> will also be const. */
244    typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType;
245
246    /**
247     *  SkAutoTUnref assumes ownership of the ref. As a result, it is an error
248     *  for the user to ref or unref through SkAutoTUnref. Therefore
249     *  SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of
250     *  skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref().
251     */
252    BlockRefType *operator->() const {
253        return static_cast<BlockRefType*>(fObj);
254    }
255    operator T*() { return fObj; }
256
257private:
258    T*  fObj;
259};
260
261class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
262public:
263    SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
264};
265
266class SkAutoRef : SkNoncopyable {
267public:
268    SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); }
269    ~SkAutoRef() { SkSafeUnref(fObj); }
270private:
271    SkRefCnt* fObj;
272};
273
274/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to
275    a SkRefCnt (or subclass) object.
276 */
277template <typename T> class SkRefPtr {
278public:
279    SkRefPtr() : fObj(NULL) {}
280    SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); }
281    SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); }
282    ~SkRefPtr() { SkSafeUnref(fObj); }
283
284    SkRefPtr& operator=(const SkRefPtr& rp) {
285        SkRefCnt_SafeAssign(fObj, rp.fObj);
286        return *this;
287    }
288    SkRefPtr& operator=(T* obj) {
289        SkRefCnt_SafeAssign(fObj, obj);
290        return *this;
291    }
292
293    T* get() const { return fObj; }
294    T& operator*() const { return *fObj; }
295    T* operator->() const { return fObj; }
296
297    typedef T* SkRefPtr::*unspecified_bool_type;
298    operator unspecified_bool_type() const {
299        return fObj ? &SkRefPtr::fObj : NULL;
300    }
301
302private:
303    T* fObj;
304};
305
306#endif
307