diff options
-rw-r--r-- | include/core/SkAtomics.h | 6 | ||||
-rw-r--r-- | src/core/SkPixelRef.cpp | 11 |
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. } |