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