From f8d5639ac11cf5cef29601d37d2b61f05502df4f Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 31 Jul 2013 19:05:05 -0700 Subject: [PATCH] backout f607ac59de19 (Bug 888548 part 2) for B2G build bustage --- mfbt/Atomics.h | 123 ++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 69 deletions(-) diff --git a/mfbt/Atomics.h b/mfbt/Atomics.h index 72cf28945788..32ab36884115 100644 --- a/mfbt/Atomics.h +++ b/mfbt/Atomics.h @@ -830,11 +830,6 @@ namespace detail { template class AtomicBase { - // We only support 32-bit types on 32-bit Windows, which constrains our - // implementation elsewhere. But we support pointer-sized types everywhere. - static_assert(sizeof(T) == 4 || (sizeof(uintptr_t) == 8 && sizeof(T) == 8), - "mozilla/Atomics.h only supports 32-bit and pointer-sized types"); - protected: typedef typename detail::AtomicIntrinsics Intrinsics; typename Intrinsics::ValueType mValue; @@ -843,12 +838,12 @@ class AtomicBase AtomicBase() : mValue() {} AtomicBase(T aInit) { Intrinsics::store(mValue, aInit); } - operator T() const { return Intrinsics::load(mValue); } + T operator++(int) { return Intrinsics::inc(mValue); } + T operator--(int) { return Intrinsics::dec(mValue); } + T operator++() { return Intrinsics::inc(mValue) + 1; } + T operator--() { return Intrinsics::dec(mValue) - 1; } - T operator=(T aValue) { - Intrinsics::store(mValue, aValue); - return aValue; - } + operator T() const { return Intrinsics::load(mValue); } /** * Performs an atomic swap operation. aValue is stored and the previous @@ -857,7 +852,6 @@ class AtomicBase T exchange(T aValue) { return Intrinsics::exchange(mValue, aValue); } - /** * Performs an atomic compare-and-swap operation and returns true if it * succeeded. This is equivalent to atomically doing @@ -878,35 +872,16 @@ class AtomicBase AtomicBase(const AtomicBase& aCopy) MOZ_DELETE; }; -template -class AtomicBaseIncDec : public AtomicBase -{ - typedef typename detail::AtomicBase Base; - - public: - AtomicBaseIncDec() : Base() {} - AtomicBaseIncDec(T aInit) : Base(aInit) {} - - using Base::operator=; - - T operator++(int) { return Base::Intrinsics::inc(Base::mValue); } - T operator--(int) { return Base::Intrinsics::dec(Base::mValue); } - T operator++() { return Base::Intrinsics::inc(Base::mValue) + 1; } - T operator--() { return Base::Intrinsics::dec(Base::mValue) - 1; } - - private: - template - AtomicBaseIncDec(const AtomicBaseIncDec& aCopy) MOZ_DELETE; -}; - } // namespace detail /** * A wrapper for a type that enforces that all memory accesses are atomic. * - * In general, where a variable |T foo| exists, |Atomic foo| can be used in - * its place. Implementations for integral and pointer types are provided - * below. + * In general, where a variable |T foo| exists, |Atomic foo| can be + * used in its place. In addition to atomic store and load operations, + * compound assignment and increment/decrement operators are implemented + * which perform the corresponding read-modify-write operation + * atomically. Finally, an atomic swap method is provided. * * Atomic accesses are sequentially consistent by default. You should * use the default unless you are tall enough to ride the @@ -918,30 +893,21 @@ class AtomicBaseIncDec : public AtomicBase * deliberate design choice that enables static atomic variables to be declared * without introducing extra static constructors. */ -template -class Atomic; - -/** - * Atomic implementation for integral types. - * - * In addition to atomic store and load operations, compound assignment and - * increment/decrement operators are implemented which perform the - * corresponding read-modify-write operation atomically. Finally, an atomic - * swap method is provided. - */ -template -class Atomic::value>::Type> - : public detail::AtomicBaseIncDec +template +class Atomic : public detail::AtomicBase { - typedef typename detail::AtomicBaseIncDec Base; + // We only support 32-bit types on 32-bit Windows, which constrains our + // implementation elsewhere. But we support pointer-sized types everywhere. + static_assert(sizeof(T) == 4 || (sizeof(uintptr_t) == 8 && sizeof(T) == 8), + "mozilla/Atomics.h only supports 32-bit and pointer-sized types"); + // Regardless of the OS, we only support integral types here. + static_assert(IsIntegral::value, "can only have integral atomic variables"); + + typedef typename detail::AtomicBase Base; public: - Atomic() : Base() {} - Atomic(T aInit) : Base(aInit) {} - - using Base::operator=; + Atomic() : detail::AtomicBase() {} + Atomic(T aInit) : detail::AtomicBase(aInit) {} T operator+=(T delta) { return Base::Intrinsics::add(Base::mValue, delta) + delta; } T operator-=(T delta) { return Base::Intrinsics::sub(Base::mValue, delta) - delta; } @@ -949,36 +915,55 @@ class Atomic::value>::Type> T operator^=(T val) { return Base::Intrinsics::xor_(Base::mValue, val) ^ val; } T operator&=(T val) { return Base::Intrinsics::and_(Base::mValue, val) & val; } + T operator=(T aValue) { + Base::Intrinsics::store(Base::mValue, aValue); + return aValue; + } + private: Atomic(Atomic& aOther) MOZ_DELETE; }; /** - * Atomic implementation for pointer types. + * A partial specialization of Atomic for pointer variables. * - * An atomic compare-and-swap primitive for pointer variables is provided, as - * are atomic increment and decement operators. Also provided are the compound - * assignment operators for addition and subtraction. Atomic swap (via - * exchange()) is included as well. + * Like Atomic, Atomic is equivalent in most respects to a regular T* + * variable. An atomic compare-and-swap primitive for pointer variables is + * provided, as are atomic increment and decement operators. Also provided + * are the compound assignment operators for addition and subtraction. + * Atomic swap (via exchange()) is included as well. + * + * Atomic accesses are sequentially consistent by default. You should + * use the default unless you are tall enough to ride the + * memory-ordering roller coaster (if you're not sure, you aren't) and + * you have a compelling reason to do otherwise. + * + * There is one exception to the case of atomic memory accesses: providing an + * initial value of the atomic value is not guaranteed to be atomic. This is a + * deliberate design choice that enables static atomic variables to be declared + * without introducing extra static constructors. */ template -class Atomic : public detail::AtomicBaseIncDec +class Atomic : public detail::AtomicBase { - typedef typename detail::AtomicBaseIncDec Base; + typedef typename detail::AtomicBase Base; public: - Atomic() : Base() {} - Atomic(T* aInit) : Base(aInit) {} + Atomic() : detail::AtomicBase() {} + Atomic(T* aInit) : detail::AtomicBase(aInit) {} - using Base::operator=; - - T* operator+=(ptrdiff_t delta) { + T* operator +=(ptrdiff_t delta) { return Base::Intrinsics::add(Base::mValue, delta) + delta; } - T* operator-=(ptrdiff_t delta) { + T* operator -=(ptrdiff_t delta) { return Base::Intrinsics::sub(Base::mValue, delta) - delta; } + T* operator=(T* aValue) { + Base::Intrinsics::store(Base::mValue, aValue); + return aValue; + } + private: Atomic(Atomic& aOther) MOZ_DELETE; };