Bug 965837 - Add bool support to mozilla::Atomic. r=froydnj

This commit is contained in:
Viktor Stanchev 2014-01-30 16:43:00 -05:00
parent 152939bb42
commit a25671c119
2 changed files with 78 additions and 1 deletions

View File

@ -934,7 +934,7 @@ class Atomic;
* swap method is provided.
*/
template<typename T, MemoryOrdering Order>
class Atomic<T, Order, typename EnableIf<IsIntegral<T>::value>::Type>
class Atomic<T, Order, typename EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value>::Type>
: public detail::AtomicBaseIncDec<T, Order>
{
typedef typename detail::AtomicBaseIncDec<T, Order> Base;
@ -1006,6 +1006,44 @@ class Atomic<T, Order, typename EnableIf<IsEnum<T>::value>::Type>
Atomic(Atomic<T, Order>& aOther) MOZ_DELETE;
};
/**
* Atomic<T> implementation for boolean types.
*
* The atomic store and load operations and the atomic swap method is provided.
*
* Note:
*
* - sizeof(Atomic<bool>) != sizeof(bool) for some implementations of
* bool and/or some implementations of std::atomic. This is allowed in
* [atomic.types.generic]p9.
*
* - It's not obvious whether the 8-bit atomic functions on Windows are always
* inlined or not. If they are not inlined, the corresponding functions in the
* runtime library are not available on Windows XP. This is why we implement
* Atomic<bool> with an underlying type of uint32_t.
*/
template<MemoryOrdering Order>
class Atomic<bool, Order>
: protected detail::AtomicBase<uint32_t, Order>
{
typedef typename detail::AtomicBase<uint32_t, Order> Base;
public:
MOZ_CONSTEXPR Atomic() : Base() {}
MOZ_CONSTEXPR Atomic(bool aInit) : Base(aInit) {}
// We provide boolean wrappers for the underlying AtomicBase methods.
operator bool() const { return Base::operator uint32_t(); }
bool operator=(bool aValue) { return Base::operator=(aValue); }
bool exchange(bool aValue) { return Base::exchange(aValue); }
bool compareExchange(bool aOldValue, bool aNewValue) {
return Base::compareExchange(aOldValue, aNewValue);
}
private:
Atomic(Atomic<bool, Order>& aOther) MOZ_DELETE;
};
} // namespace mozilla
#endif /* mozilla_Atomics_h */

View File

@ -165,6 +165,36 @@ TestEnumWithOrdering()
MOZ_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value.");
}
template <MemoryOrdering Order>
static void
TestBoolWithOrdering()
{
Atomic<bool, Order> atomic(false);
MOZ_ASSERT(atomic == false, "Atomic variable did not initialize");
// Test assignment
DebugOnly<bool> result;
result = (atomic = true);
MOZ_ASSERT(atomic == true, "Atomic assignment failed");
MOZ_ASSERT(result == true, "Atomic assignment returned the wrong value");
// Test exchange.
atomic = false;
result = atomic.exchange(true);
MOZ_ASSERT(atomic == true, "Atomic exchange did not work");
MOZ_ASSERT(result == false, "Atomic exchange returned the wrong value");
// Test CAS.
atomic = false;
DebugOnly<bool> boolResult = atomic.compareExchange(true, false);
MOZ_ASSERT(!boolResult, "CAS should have returned false.");
MOZ_ASSERT(atomic == false, "CAS shouldn't have done anything.");
boolResult = atomic.compareExchange(false, true);
MOZ_ASSERT(boolResult, "CAS should have succeeded.");
MOZ_ASSERT(atomic == true, "CAS should have changed atomic's value.");
}
template <typename T>
static void
TestType()
@ -191,6 +221,14 @@ TestEnum()
TestEnumWithOrdering<Relaxed>();
}
static void
TestBool()
{
TestBoolWithOrdering<SequentiallyConsistent>();
TestBoolWithOrdering<ReleaseAcquire>();
TestBoolWithOrdering<Relaxed>();
}
int main()
{
TestType<uint32_t>();
@ -202,4 +240,5 @@ int main()
TestPointer<uint16_t*>();
TestPointer<uint32_t*>();
TestEnum();
TestBool();
}