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 :
15 : /** \class SkRefCnt
16 :
17 : SkRefCnt is the base class for objects that may be shared by multiple
18 : objects. When a new owner wants a reference, it calls ref(). When an owner
19 : wants to release its reference, it calls unref(). When the shared object's
20 : reference count goes to zero as the result of an unref() call, its (virtual)
21 : destructor is called. It is an error for the destructor to be called
22 : explicitly (or via the object going out of scope on the stack or calling
23 : delete) if getRefCnt() > 1.
24 : */
25 : class SK_API SkRefCnt : SkNoncopyable {
26 : public:
27 : /** Default construct, initializing the reference count to 1.
28 : */
29 0 : SkRefCnt() : fRefCnt(1) {}
30 :
31 : /** Destruct, asserting that the reference count is 1.
32 : */
33 0 : virtual ~SkRefCnt() {
34 : #ifdef SK_DEBUG
35 0 : SkASSERT(fRefCnt == 1);
36 0 : fRefCnt = 0; // illegal value, to catch us if we reuse after delete
37 : #endif
38 0 : }
39 :
40 : /** Return the reference count.
41 : */
42 0 : int32_t getRefCnt() const { return fRefCnt; }
43 :
44 : /** Increment the reference count. Must be balanced by a call to unref().
45 : */
46 0 : void ref() const {
47 0 : SkASSERT(fRefCnt > 0);
48 0 : sk_atomic_inc(&fRefCnt);
49 0 : }
50 :
51 : /** Decrement the reference count. If the reference count is 1 before the
52 : decrement, then call delete on the object. Note that if this is the
53 : case, then the object needs to have been allocated via new, and not on
54 : the stack.
55 : */
56 0 : void unref() const {
57 0 : SkASSERT(fRefCnt > 0);
58 0 : if (sk_atomic_dec(&fRefCnt) == 1) {
59 0 : fRefCnt = 1; // so our destructor won't complain
60 0 : SkDELETE(this);
61 : }
62 0 : }
63 :
64 : void validate() const {
65 : SkASSERT(fRefCnt > 0);
66 : }
67 :
68 : private:
69 : mutable int32_t fRefCnt;
70 : };
71 :
72 : ///////////////////////////////////////////////////////////////////////////////
73 :
74 : /** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
75 : null in on each side of the assignment, and ensuring that ref() is called
76 : before unref(), in case the two pointers point to the same object.
77 : */
78 : #define SkRefCnt_SafeAssign(dst, src) \
79 : do { \
80 : if (src) src->ref(); \
81 : if (dst) dst->unref(); \
82 : dst = src; \
83 : } while (0)
84 :
85 :
86 : /** Check if the argument is non-null, and if so, call obj->ref()
87 : */
88 0 : template <typename T> static inline void SkSafeRef(T* obj) {
89 0 : if (obj) {
90 0 : obj->ref();
91 : }
92 0 : }
93 :
94 : /** Check if the argument is non-null, and if so, call obj->unref()
95 : */
96 0 : template <typename T> static inline void SkSafeUnref(T* obj) {
97 0 : if (obj) {
98 0 : obj->unref();
99 : }
100 0 : }
101 :
102 : ///////////////////////////////////////////////////////////////////////////////
103 :
104 : /**
105 : * Utility class that simply unref's its argument in the destructor.
106 : */
107 : template <typename T> class SkAutoTUnref : SkNoncopyable {
108 : public:
109 0 : explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
110 0 : ~SkAutoTUnref() { SkSafeUnref(fObj); }
111 :
112 : T* get() const { return fObj; }
113 :
114 : void reset(T* obj) {
115 : SkSafeUnref(fObj);
116 : fObj = obj;
117 : }
118 :
119 : /**
120 : * Return the hosted object (which may be null), transferring ownership.
121 : * The reference count is not modified, and the internal ptr is set to NULL
122 : * so unref() will not be called in our destructor. A subsequent call to
123 : * detach() will do nothing and return null.
124 : */
125 : T* detach() {
126 : T* obj = fObj;
127 : fObj = NULL;
128 : return obj;
129 : }
130 :
131 : private:
132 : T* fObj;
133 : };
134 :
135 0 : class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
136 : public:
137 0 : SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
138 : };
139 :
140 : class SkAutoRef : SkNoncopyable {
141 : public:
142 : SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); }
143 : ~SkAutoRef() { SkSafeUnref(fObj); }
144 : private:
145 : SkRefCnt* fObj;
146 : };
147 :
148 : /** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to
149 : a SkRefCnt (or subclass) object.
150 : */
151 : template <typename T> class SkRefPtr {
152 : public:
153 : SkRefPtr() : fObj(NULL) {}
154 : SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); }
155 : SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); }
156 : ~SkRefPtr() { SkSafeUnref(fObj); }
157 :
158 : SkRefPtr& operator=(const SkRefPtr& rp) {
159 : SkRefCnt_SafeAssign(fObj, rp.fObj);
160 : return *this;
161 : }
162 : SkRefPtr& operator=(T* obj) {
163 : SkRefCnt_SafeAssign(fObj, obj);
164 : return *this;
165 : }
166 :
167 : T* get() const { return fObj; }
168 : T& operator*() const { return *fObj; }
169 : T* operator->() const { return fObj; }
170 :
171 : typedef T* SkRefPtr::*unspecified_bool_type;
172 : operator unspecified_bool_type() const {
173 : return fObj ? &SkRefPtr::fObj : NULL;
174 : }
175 :
176 : private:
177 : T* fObj;
178 : };
179 :
180 : #endif
181 :
|