Synchronized::exchange
[folly.git] / folly / test / SynchronizedTest.cpp
index b734964533a72a1ed1464e349d7b78af774eafa7..c4735c2e9bbce2f0a0cd3a34409894614cbceb78 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2011-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 // @author: Andrei Alexandrescu (aalexandre)
 
 // Test bed for folly/Synchronized.h
 
+#include <folly/Synchronized.h>
 #include <folly/LockTraitsBoost.h>
 #include <folly/Portability.h>
-#include <folly/RWSpinLock.h>
 #include <folly/SharedMutex.h>
 #include <folly/SpinLock.h>
-#include <folly/Synchronized.h>
+#include <folly/portability/GTest.h>
+#include <folly/synchronization/RWSpinLock.h>
 #include <folly/test/SynchronizedTestLib.h>
-#include <gtest/gtest.h>
 
 using namespace folly::sync_tests;
 
@@ -95,6 +94,14 @@ TYPED_TEST(SynchronizedTest, ConstCopy) {
   testConstCopy<TypeParam>();
 }
 
+TYPED_TEST(SynchronizedTest, InPlaceConstruction) {
+  testInPlaceConstruction<TypeParam>();
+}
+
+TYPED_TEST(SynchronizedTest, Exchange) {
+  testExchange<TypeParam>();
+}
+
 template <class Mutex>
 class SynchronizedTimedTest : public testing::Test {};
 
@@ -146,10 +153,6 @@ TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) {
   testTimedSynchronizedWithConst<TypeParam>();
 }
 
-TYPED_TEST(SynchronizedTest, InPlaceConstruction) {
-  testInPlaceConstruction<TypeParam>();
-}
-
 using CountPair = std::pair<int, int>;
 // This class is specialized only to be uesed in SynchronizedLockTest
 class FakeMutex {
@@ -189,11 +192,6 @@ class SynchronizedLockTest : public testing::Test {
   }
 };
 
-/**
- * To avoid typing
- */
-// static constexpr auto one_ms = std::chrono::milliseconds(1);
-
 /**
  * Test mutex to help to automate assertions, taken from LockTraitsTest.cpp
  */
@@ -335,69 +333,20 @@ class FakeAllPowerfulAssertingMutex {
   }
 };
 
-// Single level of SYNCHRONIZED and UNSYNCHRONIZED, although nested test are
-// super set of it, it is possible single level test passes while nested tests
-// fail
-TEST_F(SynchronizedLockTest, SyncUnSync) {
-  folly::Synchronized<std::vector<int>, FakeMutex> obj;
-  EXPECT_EQ((CountPair{0, 0}), FakeMutex::getLockUnlockCount());
-  SYNCHRONIZED(obj) {
-    EXPECT_EQ((CountPair{1, 0}), FakeMutex::getLockUnlockCount());
-    UNSYNCHRONIZED(obj) {
-      EXPECT_EQ((CountPair{1, 1}), FakeMutex::getLockUnlockCount());
-    }
-    EXPECT_EQ((CountPair{2, 1}), FakeMutex::getLockUnlockCount());
-  }
-  EXPECT_EQ((CountPair{2, 2}), FakeMutex::getLockUnlockCount());
-}
-
-// Nested SYNCHRONIZED UNSYNCHRONIZED test, 2 levels of synchronization
-TEST_F(SynchronizedLockTest, NestedSyncUnSync) {
-  folly::Synchronized<std::vector<int>, FakeMutex> obj;
-  EXPECT_EQ((CountPair{0, 0}), FakeMutex::getLockUnlockCount());
-  SYNCHRONIZED(objCopy, obj) {
-    EXPECT_EQ((CountPair{1, 0}), FakeMutex::getLockUnlockCount());
-    SYNCHRONIZED(obj) {
-      EXPECT_EQ((CountPair{2, 0}), FakeMutex::getLockUnlockCount());
-      // Note: UNSYNCHRONIZED has always been kind of broken here.
-      // The input parameter is ignored (other than to overwrite what the input
-      // variable name refers to), and it unlocks the most object acquired in
-      // the most recent SYNCHRONIZED scope.
-      UNSYNCHRONIZED(obj) {
-        EXPECT_EQ((CountPair{2, 1}), FakeMutex::getLockUnlockCount());
-      }
-      EXPECT_EQ((CountPair{3, 1}), FakeMutex::getLockUnlockCount());
-      UNSYNCHRONIZED(obj) {
-        EXPECT_EQ((CountPair{3, 2}), FakeMutex::getLockUnlockCount());
-      }
-      EXPECT_EQ((CountPair{4, 2}), FakeMutex::getLockUnlockCount());
-    }
-    EXPECT_EQ((CountPair{4, 3}), FakeMutex::getLockUnlockCount());
-  }
-  EXPECT_EQ((CountPair{4, 4}), FakeMutex::getLockUnlockCount());
-}
-
-// Different nesting behavior, UNSYNCHRONIZED called on different depth of
-// SYNCHRONIZED
-TEST_F(SynchronizedLockTest, NestedSyncUnSync2) {
-  folly::Synchronized<std::vector<int>, FakeMutex> obj;
-  EXPECT_EQ((CountPair{0, 0}), FakeMutex::getLockUnlockCount());
-  SYNCHRONIZED(objCopy, obj) {
-    EXPECT_EQ((CountPair{1, 0}), FakeMutex::getLockUnlockCount());
-    SYNCHRONIZED(obj) {
-      EXPECT_EQ((CountPair{2, 0}), FakeMutex::getLockUnlockCount());
-      UNSYNCHRONIZED(obj) {
-        EXPECT_EQ((CountPair{2, 1}), FakeMutex::getLockUnlockCount());
-      }
-      EXPECT_EQ((CountPair{3, 1}), FakeMutex::getLockUnlockCount());
-    }
-    EXPECT_EQ((CountPair{3, 2}), FakeMutex::getLockUnlockCount());
-    UNSYNCHRONIZED(obj) {
-      EXPECT_EQ((CountPair{3, 3}), FakeMutex::getLockUnlockCount());
-    }
-    EXPECT_EQ((CountPair{4, 3}), FakeMutex::getLockUnlockCount());
-  }
-  EXPECT_EQ((CountPair{4, 4}), FakeMutex::getLockUnlockCount());
+TEST_F(SynchronizedLockTest, TestCopyConstructibleValues) {
+  struct NonCopyConstructible {
+    NonCopyConstructible(const NonCopyConstructible&) = delete;
+    NonCopyConstructible& operator=(const NonCopyConstructible&) = delete;
+  };
+  struct CopyConstructible {};
+  EXPECT_FALSE(std::is_copy_constructible<
+               folly::Synchronized<NonCopyConstructible>>::value);
+  EXPECT_FALSE(std::is_copy_assignable<
+               folly::Synchronized<NonCopyConstructible>>::value);
+  EXPECT_TRUE(std::is_copy_constructible<
+              folly::Synchronized<CopyConstructible>>::value);
+  EXPECT_TRUE(
+      std::is_copy_assignable<folly::Synchronized<CopyConstructible>>::value);
 }
 
 TEST_F(SynchronizedLockTest, UpgradableLocking) {
@@ -438,7 +387,7 @@ TEST_F(SynchronizedLockTest, UpgradableLocking) {
   // test going from upgrade to shared
   {
     auto ulock = sync.ulock();
-    auto slock = ulock.moveFromUpgradeToShared();
+    auto slock = ulock.moveFromUpgradeToRead();
     EXPECT_EQ(static_cast<bool>(ulock), false);
     EXPECT_EQ(
         globalAllPowerfulAssertingMutex.lock_state,
@@ -468,7 +417,7 @@ TEST_F(SynchronizedLockTest, UpgradableLocking) {
   // test going from exclusive to shared
   {
     auto wlock = sync.wlock();
-    auto slock = wlock.moveFromWriteToShared();
+    auto slock = wlock.moveFromWriteToRead();
     EXPECT_EQ(static_cast<bool>(wlock), false);
     EXPECT_EQ(
         globalAllPowerfulAssertingMutex.lock_state,
@@ -534,7 +483,7 @@ TEST_F(SynchronizedLockTest, UpgradableLockingWithULock) {
         globalAllPowerfulAssertingMutex.lock_state,
         FakeAllPowerfulAssertingMutexInternal::CurrentLockState::UPGRADE);
 
-    auto slock = ulock.moveFromUpgradeToShared();
+    auto slock = ulock.moveFromUpgradeToRead();
     EXPECT_EQ(static_cast<bool>(ulock), false);
     EXPECT_EQ(
         globalAllPowerfulAssertingMutex.lock_state,
@@ -553,7 +502,7 @@ TEST_F(SynchronizedLockTest, UpgradableLockingWithULock) {
         globalAllPowerfulAssertingMutex.lock_state,
         FakeAllPowerfulAssertingMutexInternal::CurrentLockState::UNIQUE);
 
-    auto slock = wlock.moveFromWriteToShared();
+    auto slock = wlock.moveFromWriteToRead();
     EXPECT_EQ(static_cast<bool>(wlock), false);
     EXPECT_EQ(
         globalAllPowerfulAssertingMutex.lock_state,