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