aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkRefCnt.h
diff options
context:
space:
mode:
authorGravatar bungeman <bungeman@google.com>2016-04-08 06:58:51 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-08 06:58:52 -0700
commit2c4bd0798e929acb9663668985eabe74d7378c46 (patch)
tree228e7970c5ab59b655726a28ffc9849a9b8746eb /include/core/SkRefCnt.h
parent6a5d7139ff17a2dfdf136de35f7dd9c94c1f648b (diff)
Convert SkRefCnt to std::atomic.
This enables removing the more complicated atomic shims from SkAtomics.h. TBR=reed This doesn't actually change any API. CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-TSAN-Trybot,Test-Ubuntu-GCC-Golo-GPU-GT610-x86_64-Release-TSAN-Trybot Review URL: https://codereview.chromium.org/1867863002
Diffstat (limited to 'include/core/SkRefCnt.h')
-rw-r--r--include/core/SkRefCnt.h56
1 files changed, 31 insertions, 25 deletions
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
index 46d475e5e4..abcda7e990 100644
--- a/include/core/SkRefCnt.h
+++ b/include/core/SkRefCnt.h
@@ -8,9 +8,9 @@
#ifndef SkRefCnt_DEFINED
#define SkRefCnt_DEFINED
-#include "../private/SkAtomics.h"
#include "../private/SkTLogic.h"
#include "SkTypes.h"
+#include <atomic>
#include <functional>
#include <memory>
#include <utility>
@@ -37,21 +37,28 @@ public:
*/
virtual ~SkRefCntBase() {
#ifdef SK_DEBUG
- SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt);
- fRefCnt = 0; // illegal value, to catch us if we reuse after delete
+ SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt());
+ // illegal value, to catch us if we reuse after delete
+ fRefCnt.store(0, std::memory_order_relaxed);
#endif
}
#ifdef SK_DEBUG
/** Return the reference count. Use only for debugging. */
- int32_t getRefCnt() const { return fRefCnt; }
+ int32_t getRefCnt() const {
+ return fRefCnt.load(std::memory_order_relaxed);
+ }
+
+ void validate() const {
+ SkASSERT(getRefCnt() > 0);
+ }
#endif
/** May return true if the caller is the only owner.
* Ensures that all previous owner's actions are complete.
*/
bool unique() const {
- if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) {
+ if (1 == fRefCnt.load(std::memory_order_acquire)) {
// The acquire barrier is only really needed if we return true. It
// prevents code conditioned on the result of unique() from running
// until previous owners are all totally done calling unref().
@@ -68,11 +75,12 @@ public:
// go to zero, but not below, prior to reusing the object. This breaks
// the use of unique() on such objects and as such should be removed
// once the Android code is fixed.
- SkASSERT(fRefCnt >= 0);
+ SkASSERT(getRefCnt() >= 0);
#else
- SkASSERT(fRefCnt > 0);
+ SkASSERT(getRefCnt() > 0);
#endif
- (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No barrier required.
+ // No barrier required.
+ (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
}
/** Decrement the reference count. If the reference count is 1 before the
@@ -80,21 +88,15 @@ public:
the object needs to have been allocated via new, and not on the stack.
*/
void unref() const {
- SkASSERT(fRefCnt > 0);
+ SkASSERT(getRefCnt() > 0);
// A release here acts in place of all releases we "should" have been doing in ref().
- if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
+ if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
// Like unique(), the acquire is only needed on success, to make sure
// code in internal_dispose() doesn't happen before the decrement.
this->internal_dispose();
}
}
-#ifdef SK_DEBUG
- void validate() const {
- SkASSERT(fRefCnt > 0);
- }
-#endif
-
protected:
/**
* Allow subclasses to call this if they've overridden internal_dispose
@@ -104,8 +106,8 @@ protected:
*/
void internal_dispose_restore_refcnt_to_1() const {
#ifdef SK_DEBUG
- SkASSERT(0 == fRefCnt);
- fRefCnt = 1;
+ SkASSERT(0 == getRefCnt());
+ fRefCnt.store(1, std::memory_order_relaxed);
#endif
}
@@ -122,7 +124,7 @@ private:
// and conditionally call SkRefCnt::internal_dispose().
friend class SkWeakRefCnt;
- mutable int32_t fRefCnt;
+ mutable std::atomic<int32_t> fRefCnt;
typedef SkNoncopyable INHERITED;
};
@@ -215,25 +217,29 @@ template <typename Derived>
class SkNVRefCnt : SkNoncopyable {
public:
SkNVRefCnt() : fRefCnt(1) {}
- ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); }
+ ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt()); }
// Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
// - unique() needs acquire when it returns true, and no barrier if it returns false;
// - ref() doesn't need any barrier;
// - unref() needs a release barrier, and an acquire if it's going to call delete.
- bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); }
- void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); }
+ bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
+ void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
void unref() const {
- if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
- SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert
+ if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
+ // restore the 1 for our destructor's assert
+ SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));
delete (const Derived*)this;
}
}
void deref() const { this->unref(); }
private:
- mutable int32_t fRefCnt;
+ mutable std::atomic<int32_t> fRefCnt;
+ int32_t getRefCnt() const {
+ return fRefCnt.load(std::memory_order_relaxed);
+ }
};
///////////////////////////////////////////////////////////////////////////////////////////////////