Bug 888548 - Part 3: Add enum support to mozilla::Atomic<T>. r=froydnj
☠☠ backed out by ff607d314da1 ☠ ☠
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Wed, 31 Jul 2013 21:15:25 -0400
changeset 153133 fc98067f0aa48e7cf09ef10cd2d2773ad7a243ad
parent 153132 f607ac59de19d282719d3359cea88728519eda3f
child 153134 07d92b28f7215d4c429213261e817954790c104b
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs888548
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 888548 - Part 3: Add enum support to mozilla::Atomic<T>. r=froydnj Due to a bug in GCC, the compareExchange function is not available with enum types.
mfbt/Atomics.h
mfbt/tests/TestAtomics.cpp
--- a/mfbt/Atomics.h
+++ b/mfbt/Atomics.h
@@ -978,11 +978,32 @@ class Atomic<T*, Order> : public detail:
     T* operator-=(ptrdiff_t delta) {
       return Base::Intrinsics::sub(Base::mValue, delta) - delta;
     }
 
   private:
     Atomic(Atomic<T*, Order>& aOther) MOZ_DELETE;
 };
 
+/**
+ * Atomic<T> implementation for enum types.
+ *
+ * The atomic store and load operations and the atomic swap method is provided.
+ */
+template<typename T, MemoryOrdering Order>
+class Atomic<T, Order, typename EnableIf<IsEnum<T>::value>::Type>
+  : public detail::AtomicBase<T, Order>
+{
+    typedef typename detail::AtomicBase<T, Order> Base;
+
+  public:
+    Atomic() : Base() {}
+    Atomic(T aInit) : Base(aInit) {}
+
+    using Base::operator=;
+
+  private:
+    Atomic(Atomic<T, Order>& aOther) MOZ_DELETE;
+};
+
 } // namespace mozilla
 
 #endif /* mozilla_Atomics_h */
--- a/mfbt/tests/TestAtomics.cpp
+++ b/mfbt/tests/TestAtomics.cpp
@@ -123,16 +123,53 @@ TestPointerWithOrdering()
   MOZ_ASSERT(!boolResult, "CAS should have returned false.");
   MOZ_ASSERT(atomic == array1, "CAS shouldn't have done anything.");
 
   boolResult = atomic.compareExchange(array1, array1 + 3);
   MOZ_ASSERT(boolResult, "CAS should have succeeded.");
   MOZ_ASSERT(atomic == array1 + 3, "CAS should have changed atomic's value.");
 }
 
+template<MemoryOrdering Order>
+static void
+TestEnumWithOrdering()
+{
+  enum EnumType {
+    EnumType_0 = 0,
+    EnumType_1 = 1,
+    EnumType_2 = 2,
+    EnumType_3 = 3
+  };
+
+  Atomic<EnumType, Order> atomic(EnumType_2);
+  MOZ_ASSERT(atomic == EnumType_2, "Atomic variable did not initialize");
+
+  // Test assignment
+  DebugOnly<EnumType> result;
+  result = (atomic = EnumType_3);
+  MOZ_ASSERT(atomic == EnumType_3, "Atomic assignment failed");
+  MOZ_ASSERT(result == EnumType_3, "Atomic assignment returned the wrong value");
+
+  // Test exchange.
+  atomic = EnumType_1;
+  result = atomic.exchange(EnumType_2);
+  MOZ_ASSERT(atomic == EnumType_2, "Atomic exchange did not work");
+  MOZ_ASSERT(result == EnumType_1, "Atomic exchange returned the wrong value");
+
+  // Test CAS.
+  atomic = EnumType_1;
+  DebugOnly<bool> boolResult = atomic.compareExchange(EnumType_0, EnumType_2);
+  MOZ_ASSERT(!boolResult, "CAS should have returned false.");
+  MOZ_ASSERT(atomic == EnumType_1, "CAS shouldn't have done anything.");
+
+  boolResult = atomic.compareExchange(EnumType_1, EnumType_3);
+  MOZ_ASSERT(boolResult, "CAS should have succeeded.");
+  MOZ_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value.");
+}
+
 template <typename T>
 static void
 TestType()
 {
   TestTypeWithOrdering<T, SequentiallyConsistent>();
   TestTypeWithOrdering<T, ReleaseAcquire>();
   TestTypeWithOrdering<T, Relaxed>();
 }
@@ -141,19 +178,28 @@ template<typename T>
 static void
 TestPointer()
 {
   TestPointerWithOrdering<T, SequentiallyConsistent>();
   TestPointerWithOrdering<T, ReleaseAcquire>();
   TestPointerWithOrdering<T, Relaxed>();
 }
 
+static void
+TestEnum()
+{
+  TestEnumWithOrdering<SequentiallyConsistent>();
+  TestEnumWithOrdering<ReleaseAcquire>();
+  TestEnumWithOrdering<Relaxed>();
+}
+
 int main()
 {
   TestType<uint32_t>();
   TestType<int32_t>();
   TestType<intptr_t>();
   TestType<uintptr_t>();
   TestPointer<int>();
   TestPointer<float>();
   TestPointer<uint16_t*>();
   TestPointer<uint32_t*>();
+  TestEnum();
 }