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