Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: include/core/SkRefCnt.h

Issue 1867863002: Convert SkRefCnt to std::atomic. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Restore to 1. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkPathRef.h ('k') | include/private/SkAtomics.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « include/core/SkPathRef.h ('k') | include/private/SkAtomics.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698