| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkRefCnt_DEFINED | 8 #ifndef SkRefCnt_DEFINED |
| 9 #define SkRefCnt_DEFINED | 9 #define SkRefCnt_DEFINED |
| 10 | 10 |
| 11 #include "../private/SkAtomics.h" | |
| 12 #include "../private/SkTLogic.h" | 11 #include "../private/SkTLogic.h" |
| 13 #include "SkTypes.h" | 12 #include "SkTypes.h" |
| 13 #include <atomic> |
| 14 #include <functional> | 14 #include <functional> |
| 15 #include <memory> | 15 #include <memory> |
| 16 #include <utility> | 16 #include <utility> |
| 17 | 17 |
| 18 #define SK_SUPPORT_TRANSITION_TO_SP_INTERFACES | 18 #define SK_SUPPORT_TRANSITION_TO_SP_INTERFACES |
| 19 | 19 |
| 20 /** \class SkRefCntBase | 20 /** \class SkRefCntBase |
| 21 | 21 |
| 22 SkRefCntBase is the base class for objects that may be shared by multiple | 22 SkRefCntBase is the base class for objects that may be shared by multiple |
| 23 objects. When an existing owner wants to share a reference, it calls ref(). | 23 objects. When an existing owner wants to share a reference, it calls ref(). |
| 24 When an owner wants to release its reference, it calls unref(). When the | 24 When an owner wants to release its reference, it calls unref(). When the |
| 25 shared object's reference count goes to zero as the result of an unref() | 25 shared object's reference count goes to zero as the result of an unref() |
| 26 call, its (virtual) destructor is called. It is an error for the | 26 call, its (virtual) destructor is called. It is an error for the |
| 27 destructor to be called explicitly (or via the object going out of scope on | 27 destructor to be called explicitly (or via the object going out of scope on |
| 28 the stack or calling delete) if getRefCnt() > 1. | 28 the stack or calling delete) if getRefCnt() > 1. |
| 29 */ | 29 */ |
| 30 class SK_API SkRefCntBase : SkNoncopyable { | 30 class SK_API SkRefCntBase : SkNoncopyable { |
| 31 public: | 31 public: |
| 32 /** Default construct, initializing the reference count to 1. | 32 /** Default construct, initializing the reference count to 1. |
| 33 */ | 33 */ |
| 34 SkRefCntBase() : fRefCnt(1) {} | 34 SkRefCntBase() : fRefCnt(1) {} |
| 35 | 35 |
| 36 /** Destruct, asserting that the reference count is 1. | 36 /** Destruct, asserting that the reference count is 1. |
| 37 */ | 37 */ |
| 38 virtual ~SkRefCntBase() { | 38 virtual ~SkRefCntBase() { |
| 39 #ifdef SK_DEBUG | 39 #ifdef SK_DEBUG |
| 40 SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt); | 40 SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt()); |
| 41 fRefCnt = 0; // illegal value, to catch us if we reuse after delete | 41 // illegal value, to catch us if we reuse after delete |
| 42 fRefCnt.store(0, std::memory_order_relaxed); |
| 42 #endif | 43 #endif |
| 43 } | 44 } |
| 44 | 45 |
| 45 #ifdef SK_DEBUG | 46 #ifdef SK_DEBUG |
| 46 /** Return the reference count. Use only for debugging. */ | 47 /** Return the reference count. Use only for debugging. */ |
| 47 int32_t getRefCnt() const { return fRefCnt; } | 48 int32_t getRefCnt() const { |
| 49 return fRefCnt.load(std::memory_order_relaxed); |
| 50 } |
| 51 |
| 52 void validate() const { |
| 53 SkASSERT(getRefCnt() > 0); |
| 54 } |
| 48 #endif | 55 #endif |
| 49 | 56 |
| 50 /** May return true if the caller is the only owner. | 57 /** May return true if the caller is the only owner. |
| 51 * Ensures that all previous owner's actions are complete. | 58 * Ensures that all previous owner's actions are complete. |
| 52 */ | 59 */ |
| 53 bool unique() const { | 60 bool unique() const { |
| 54 if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) { | 61 if (1 == fRefCnt.load(std::memory_order_acquire)) { |
| 55 // The acquire barrier is only really needed if we return true. It | 62 // The acquire barrier is only really needed if we return true. It |
| 56 // prevents code conditioned on the result of unique() from running | 63 // prevents code conditioned on the result of unique() from running |
| 57 // until previous owners are all totally done calling unref(). | 64 // until previous owners are all totally done calling unref(). |
| 58 return true; | 65 return true; |
| 59 } | 66 } |
| 60 return false; | 67 return false; |
| 61 } | 68 } |
| 62 | 69 |
| 63 /** Increment the reference count. Must be balanced by a call to unref(). | 70 /** Increment the reference count. Must be balanced by a call to unref(). |
| 64 */ | 71 */ |
| 65 void ref() const { | 72 void ref() const { |
| 66 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 73 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 67 // Android employs some special subclasses that enable the fRefCnt to | 74 // Android employs some special subclasses that enable the fRefCnt to |
| 68 // go to zero, but not below, prior to reusing the object. This breaks | 75 // go to zero, but not below, prior to reusing the object. This breaks |
| 69 // the use of unique() on such objects and as such should be removed | 76 // the use of unique() on such objects and as such should be removed |
| 70 // once the Android code is fixed. | 77 // once the Android code is fixed. |
| 71 SkASSERT(fRefCnt >= 0); | 78 SkASSERT(getRefCnt() >= 0); |
| 72 #else | 79 #else |
| 73 SkASSERT(fRefCnt > 0); | 80 SkASSERT(getRefCnt() > 0); |
| 74 #endif | 81 #endif |
| 75 (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No
barrier required. | 82 // No barrier required. |
| 83 (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); |
| 76 } | 84 } |
| 77 | 85 |
| 78 /** Decrement the reference count. If the reference count is 1 before the | 86 /** Decrement the reference count. If the reference count is 1 before the |
| 79 decrement, then delete the object. Note that if this is the case, then | 87 decrement, then delete the object. Note that if this is the case, then |
| 80 the object needs to have been allocated via new, and not on the stack. | 88 the object needs to have been allocated via new, and not on the stack. |
| 81 */ | 89 */ |
| 82 void unref() const { | 90 void unref() const { |
| 83 SkASSERT(fRefCnt > 0); | 91 SkASSERT(getRefCnt() > 0); |
| 84 // A release here acts in place of all releases we "should" have been do
ing in ref(). | 92 // A release here acts in place of all releases we "should" have been do
ing in ref(). |
| 85 if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { | 93 if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) { |
| 86 // Like unique(), the acquire is only needed on success, to make sur
e | 94 // Like unique(), the acquire is only needed on success, to make sur
e |
| 87 // code in internal_dispose() doesn't happen before the decrement. | 95 // code in internal_dispose() doesn't happen before the decrement. |
| 88 this->internal_dispose(); | 96 this->internal_dispose(); |
| 89 } | 97 } |
| 90 } | 98 } |
| 91 | 99 |
| 92 #ifdef SK_DEBUG | |
| 93 void validate() const { | |
| 94 SkASSERT(fRefCnt > 0); | |
| 95 } | |
| 96 #endif | |
| 97 | |
| 98 protected: | 100 protected: |
| 99 /** | 101 /** |
| 100 * Allow subclasses to call this if they've overridden internal_dispose | 102 * Allow subclasses to call this if they've overridden internal_dispose |
| 101 * so they can reset fRefCnt before the destructor is called. Should only | 103 * so they can reset fRefCnt before the destructor is called. Should only |
| 102 * be called right before calling through to inherited internal_dispose() | 104 * be called right before calling through to inherited internal_dispose() |
| 103 * or before calling the destructor. | 105 * or before calling the destructor. |
| 104 */ | 106 */ |
| 105 void internal_dispose_restore_refcnt_to_1() const { | 107 void internal_dispose_restore_refcnt_to_1() const { |
| 106 #ifdef SK_DEBUG | 108 #ifdef SK_DEBUG |
| 107 SkASSERT(0 == fRefCnt); | 109 SkASSERT(0 == getRefCnt()); |
| 108 fRefCnt = 1; | 110 fRefCnt.store(1, std::memory_order_relaxed); |
| 109 #endif | 111 #endif |
| 110 } | 112 } |
| 111 | 113 |
| 112 private: | 114 private: |
| 113 /** | 115 /** |
| 114 * Called when the ref count goes to 0. | 116 * Called when the ref count goes to 0. |
| 115 */ | 117 */ |
| 116 virtual void internal_dispose() const { | 118 virtual void internal_dispose() const { |
| 117 this->internal_dispose_restore_refcnt_to_1(); | 119 this->internal_dispose_restore_refcnt_to_1(); |
| 118 delete this; | 120 delete this; |
| 119 } | 121 } |
| 120 | 122 |
| 121 // The following friends are those which override internal_dispose() | 123 // The following friends are those which override internal_dispose() |
| 122 // and conditionally call SkRefCnt::internal_dispose(). | 124 // and conditionally call SkRefCnt::internal_dispose(). |
| 123 friend class SkWeakRefCnt; | 125 friend class SkWeakRefCnt; |
| 124 | 126 |
| 125 mutable int32_t fRefCnt; | 127 mutable std::atomic<int32_t> fRefCnt; |
| 126 | 128 |
| 127 typedef SkNoncopyable INHERITED; | 129 typedef SkNoncopyable INHERITED; |
| 128 }; | 130 }; |
| 129 | 131 |
| 130 #ifdef SK_REF_CNT_MIXIN_INCLUDE | 132 #ifdef SK_REF_CNT_MIXIN_INCLUDE |
| 131 // It is the responsibility of the following include to define the type SkRefCnt
. | 133 // It is the responsibility of the following include to define the type SkRefCnt
. |
| 132 // This SkRefCnt should normally derive from SkRefCntBase. | 134 // This SkRefCnt should normally derive from SkRefCntBase. |
| 133 #include SK_REF_CNT_MIXIN_INCLUDE | 135 #include SK_REF_CNT_MIXIN_INCLUDE |
| 134 #else | 136 #else |
| 135 class SK_API SkRefCnt : public SkRefCntBase { }; | 137 class SK_API SkRefCnt : public SkRefCntBase { }; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} | 210 SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} |
| 209 }; | 211 }; |
| 210 #define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) | 212 #define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) |
| 211 | 213 |
| 212 // This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead o
f 8 or 16. | 214 // This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead o
f 8 or 16. |
| 213 // There's only benefit to using this if the deriving class does not otherwise n
eed a vtable. | 215 // There's only benefit to using this if the deriving class does not otherwise n
eed a vtable. |
| 214 template <typename Derived> | 216 template <typename Derived> |
| 215 class SkNVRefCnt : SkNoncopyable { | 217 class SkNVRefCnt : SkNoncopyable { |
| 216 public: | 218 public: |
| 217 SkNVRefCnt() : fRefCnt(1) {} | 219 SkNVRefCnt() : fRefCnt(1) {} |
| 218 ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); } | 220 ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt());
} |
| 219 | 221 |
| 220 // Implementation is pretty much the same as SkRefCntBase. All required barr
iers are the same: | 222 // Implementation is pretty much the same as SkRefCntBase. All required barr
iers are the same: |
| 221 // - unique() needs acquire when it returns true, and no barrier if it ret
urns false; | 223 // - unique() needs acquire when it returns true, and no barrier if it ret
urns false; |
| 222 // - ref() doesn't need any barrier; | 224 // - ref() doesn't need any barrier; |
| 223 // - unref() needs a release barrier, and an acquire if it's going to call
delete. | 225 // - unref() needs a release barrier, and an acquire if it's going to call
delete. |
| 224 | 226 |
| 225 bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_a
cquire); } | 227 bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); } |
| 226 void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_orde
r_relaxed); } | 228 void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); } |
| 227 void unref() const { | 229 void unref() const { |
| 228 if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { | 230 if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) { |
| 229 SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's ass
ert | 231 // restore the 1 for our destructor's assert |
| 232 SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed)); |
| 230 delete (const Derived*)this; | 233 delete (const Derived*)this; |
| 231 } | 234 } |
| 232 } | 235 } |
| 233 void deref() const { this->unref(); } | 236 void deref() const { this->unref(); } |
| 234 | 237 |
| 235 private: | 238 private: |
| 236 mutable int32_t fRefCnt; | 239 mutable std::atomic<int32_t> fRefCnt; |
| 240 int32_t getRefCnt() const { |
| 241 return fRefCnt.load(std::memory_order_relaxed); |
| 242 } |
| 237 }; | 243 }; |
| 238 | 244 |
| 239 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 245 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 240 | 246 |
| 241 /** | 247 /** |
| 242 * Shared pointer class to wrap classes that support a ref()/unref() interface. | 248 * Shared pointer class to wrap classes that support a ref()/unref() interface. |
| 243 * | 249 * |
| 244 * This can be used for classes inheriting from SkRefCnt, but it also works for
other | 250 * This can be used for classes inheriting from SkRefCnt, but it also works for
other |
| 245 * classes that match the interface, but have different internal choices: e.g.
the hosted class | 251 * classes that match the interface, but have different internal choices: e.g.
the hosted class |
| 246 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk
_sp. | 252 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk
_sp. |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 * | 453 * |
| 448 * This function may be helpful while we convert callers from ptr-based to sk_s
p-based parameters. | 454 * This function may be helpful while we convert callers from ptr-based to sk_s
p-based parameters. |
| 449 */ | 455 */ |
| 450 template <typename T> sk_sp<T> sk_ref_sp(T* obj) { | 456 template <typename T> sk_sp<T> sk_ref_sp(T* obj) { |
| 451 return sk_sp<T>(SkSafeRef(obj)); | 457 return sk_sp<T>(SkSafeRef(obj)); |
| 452 } | 458 } |
| 453 | 459 |
| 454 #endif | 460 #endif |
| 455 | 461 |
| 456 #endif | 462 #endif |
| OLD | NEW |