aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkAtomics.h6
-rw-r--r--src/core/SkPixelRef.cpp11
2 files changed, 14 insertions, 3 deletions
diff --git a/include/core/SkAtomics.h b/include/core/SkAtomics.h
index d61b47a4fd..cdd39ef4b7 100644
--- a/include/core/SkAtomics.h
+++ b/include/core/SkAtomics.h
@@ -42,6 +42,12 @@ public:
void store(const T& val, sk_memory_order mo = sk_memory_order_seq_cst) {
sk_atomic_store(&fVal, val, mo);
}
+
+ bool compare_exchange(T* expected, const T& desired,
+ sk_memory_order success = sk_memory_order_seq_cst,
+ sk_memory_order failure = sk_memory_order_seq_cst) {
+ return sk_atomic_compare_exchange(&fVal, expected, desired, success, failure);
+ }
private:
T fVal;
};
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index bfee3bb549..dea8c8aed0 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -207,9 +207,14 @@ bool SkPixelRef::onLockPixelsAreWritable() const {
uint32_t SkPixelRef::getGenerationID() const {
uint32_t id = fTaggedGenID.load();
if (0 == id) {
- id = next_gen_id();
- fTaggedGenID.store(id | 1u); // TODO(mtklein): should become a compare-and-swap
- SkASSERT(this->genIDIsUnique());
+ uint32_t next = next_gen_id() | 1u;
+ if (fTaggedGenID.compare_exchange(&id, next)) {
+ id = next; // There was no race or we won the race. fTaggedGenID is next now.
+ } else {
+ // We lost a race to set fTaggedGenID. compare_exchange() filled id with the winner.
+ }
+ // We can't quite SkASSERT(this->genIDIsUnique()). It could be non-unique
+ // if we got here via the else path (pretty unlikely, but possible).
}
return id & ~1u; // Mask off bottom unique bit.
}