1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/core/SkWeakRefCnt.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef SkWeakRefCnt_DEFINED 1.12 +#define SkWeakRefCnt_DEFINED 1.13 + 1.14 +#include "SkRefCnt.h" 1.15 +#include "SkThread.h" 1.16 + 1.17 +/** \class SkWeakRefCnt 1.18 + 1.19 + SkWeakRefCnt is the base class for objects that may be shared by multiple 1.20 + objects. When an existing strong owner wants to share a reference, it calls 1.21 + ref(). When a strong owner wants to release its reference, it calls 1.22 + unref(). When the shared object's strong reference count goes to zero as 1.23 + the result of an unref() call, its (virtual) weak_dispose method is called. 1.24 + It is an error for the destructor to be called explicitly (or via the 1.25 + object going out of scope on the stack or calling delete) if 1.26 + getRefCnt() > 1. 1.27 + 1.28 + In addition to strong ownership, an owner may instead obtain a weak 1.29 + reference by calling weak_ref(). A call to weak_ref() must be balanced by a 1.30 + call to weak_unref(). To obtain a strong reference from a weak reference, 1.31 + call try_ref(). If try_ref() returns true, the owner's pointer is now also 1.32 + a strong reference on which unref() must be called. Note that this does not 1.33 + affect the original weak reference, weak_unref() must still be called. When 1.34 + the weak reference count goes to zero, the object is deleted. While the 1.35 + weak reference count is positive and the strong reference count is zero the 1.36 + object still exists, but will be in the disposed state. It is up to the 1.37 + object to define what this means. 1.38 + 1.39 + Note that a strong reference implicitly implies a weak reference. As a 1.40 + result, it is allowable for the owner of a strong ref to call try_ref(). 1.41 + This will have the same effect as calling ref(), but may be more expensive. 1.42 + 1.43 + Example: 1.44 + 1.45 + SkWeakRefCnt myRef = strongRef.weak_ref(); 1.46 + ... // strongRef.unref() may or may not be called 1.47 + if (myRef.try_ref()) { 1.48 + ... // use myRef 1.49 + myRef.unref(); 1.50 + } else { 1.51 + // myRef is in the disposed state 1.52 + } 1.53 + myRef.weak_unref(); 1.54 +*/ 1.55 +class SK_API SkWeakRefCnt : public SkRefCnt { 1.56 +public: 1.57 + SK_DECLARE_INST_COUNT(SkWeakRefCnt) 1.58 + 1.59 + /** Default construct, initializing the reference counts to 1. 1.60 + The strong references collectively hold one weak reference. When the 1.61 + strong reference count goes to zero, the collectively held weak 1.62 + reference is released. 1.63 + */ 1.64 + SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {} 1.65 + 1.66 + /** Destruct, asserting that the weak reference count is 1. 1.67 + */ 1.68 + virtual ~SkWeakRefCnt() { 1.69 +#ifdef SK_DEBUG 1.70 + SkASSERT(fWeakCnt == 1); 1.71 + fWeakCnt = 0; 1.72 +#endif 1.73 + } 1.74 + 1.75 + /** Return the weak reference count. 1.76 + */ 1.77 + int32_t getWeakCnt() const { return fWeakCnt; } 1.78 + 1.79 +#ifdef SK_DEBUG 1.80 + void validate() const { 1.81 + this->INHERITED::validate(); 1.82 + SkASSERT(fWeakCnt > 0); 1.83 + } 1.84 +#endif 1.85 + 1.86 + /** Creates a strong reference from a weak reference, if possible. The 1.87 + caller must already be an owner. If try_ref() returns true the owner 1.88 + is in posession of an additional strong reference. Both the original 1.89 + reference and new reference must be properly unreferenced. If try_ref() 1.90 + returns false, no strong reference could be created and the owner's 1.91 + reference is in the same state as before the call. 1.92 + */ 1.93 + bool SK_WARN_UNUSED_RESULT try_ref() const { 1.94 + if (sk_atomic_conditional_inc(&fRefCnt) != 0) { 1.95 + // Acquire barrier (L/SL), if not provided above. 1.96 + // Prevents subsequent code from happening before the increment. 1.97 + sk_membar_acquire__after_atomic_conditional_inc(); 1.98 + return true; 1.99 + } 1.100 + return false; 1.101 + } 1.102 + 1.103 + /** Increment the weak reference count. Must be balanced by a call to 1.104 + weak_unref(). 1.105 + */ 1.106 + void weak_ref() const { 1.107 + SkASSERT(fRefCnt > 0); 1.108 + SkASSERT(fWeakCnt > 0); 1.109 + sk_atomic_inc(&fWeakCnt); // No barrier required. 1.110 + } 1.111 + 1.112 + /** Decrement the weak reference count. If the weak reference count is 1 1.113 + before the decrement, then call delete on the object. Note that if this 1.114 + is the case, then the object needs to have been allocated via new, and 1.115 + not on the stack. 1.116 + */ 1.117 + void weak_unref() const { 1.118 + SkASSERT(fWeakCnt > 0); 1.119 + // Release barrier (SL/S), if not provided below. 1.120 + if (sk_atomic_dec(&fWeakCnt) == 1) { 1.121 + // Acquire barrier (L/SL), if not provided above. 1.122 + // Prevents code in destructor from happening before the decrement. 1.123 + sk_membar_acquire__after_atomic_dec(); 1.124 +#ifdef SK_DEBUG 1.125 + // so our destructor won't complain 1.126 + fWeakCnt = 1; 1.127 +#endif 1.128 + this->INHERITED::internal_dispose(); 1.129 + } 1.130 + } 1.131 + 1.132 + /** Returns true if there are no strong references to the object. When this 1.133 + is the case all future calls to try_ref() will return false. 1.134 + */ 1.135 + bool weak_expired() const { 1.136 + return fRefCnt == 0; 1.137 + } 1.138 + 1.139 +protected: 1.140 + /** Called when the strong reference count goes to zero. This allows the 1.141 + object to free any resources it may be holding. Weak references may 1.142 + still exist and their level of allowed access to the object is defined 1.143 + by the object's class. 1.144 + */ 1.145 + virtual void weak_dispose() const { 1.146 + } 1.147 + 1.148 +private: 1.149 + /** Called when the strong reference count goes to zero. Calls weak_dispose 1.150 + on the object and releases the implicit weak reference held 1.151 + collectively by the strong references. 1.152 + */ 1.153 + virtual void internal_dispose() const SK_OVERRIDE { 1.154 + weak_dispose(); 1.155 + weak_unref(); 1.156 + } 1.157 + 1.158 + /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */ 1.159 + mutable int32_t fWeakCnt; 1.160 + 1.161 + typedef SkRefCnt INHERITED; 1.162 +}; 1.163 + 1.164 +#endif