Commit ae099ba2 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by facebook-github-bot-9

Use type-parameterized test cases in folly/test/SynchronizedTest.cpp

Summary: [Folly] Use type-parameterized test cases in `folly/test/SynchronizedTest.cpp`.

And some cleanups.

Reviewed By: @nbronson

Differential Revision: D2428287
parent 814b989e
...@@ -740,11 +740,6 @@ class RWTicketSpinLockT : boost::noncopyable { ...@@ -740,11 +740,6 @@ class RWTicketSpinLockT : boost::noncopyable {
friend void acquireReadWrite(RWTicketSpinLockT& mutex) { friend void acquireReadWrite(RWTicketSpinLockT& mutex) {
mutex.lock(); mutex.lock();
} }
friend bool acquireReadWrite(RWTicketSpinLockT& mutex,
unsigned int milliseconds) {
mutex.lock();
return true;
}
friend void releaseRead(RWTicketSpinLockT& mutex) { friend void releaseRead(RWTicketSpinLockT& mutex) {
mutex.unlock_shared(); mutex.unlock_shared();
} }
......
...@@ -1379,6 +1379,12 @@ class SharedMutexImpl { ...@@ -1379,6 +1379,12 @@ class SharedMutexImpl {
friend void acquireReadWrite(SharedMutexImpl& lock) { lock.lock(); } friend void acquireReadWrite(SharedMutexImpl& lock) { lock.lock(); }
friend void releaseRead(SharedMutexImpl& lock) { lock.unlock_shared(); } friend void releaseRead(SharedMutexImpl& lock) { lock.unlock_shared(); }
friend void releaseReadWrite(SharedMutexImpl& lock) { lock.unlock(); } friend void releaseReadWrite(SharedMutexImpl& lock) { lock.unlock(); }
friend bool acquireRead(SharedMutexImpl& lock, unsigned int ms) {
return lock.try_lock_shared_for(std::chrono::milliseconds(ms));
}
friend bool acquireReadWrite(SharedMutexImpl& lock, unsigned int ms) {
return lock.try_lock_for(std::chrono::milliseconds(ms));
}
}; };
#define COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(type) \ #define COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(type) \
......
...@@ -54,46 +54,53 @@ enum InternalDoNotUse {}; ...@@ -54,46 +54,53 @@ enum InternalDoNotUse {};
*/ */
template <class T> template <class T>
struct HasLockUnlock { struct HasLockUnlock {
enum { value = IsOneOf<T, enum { value = IsOneOf<T
std::mutex, std::recursive_mutex, , std::mutex
boost::mutex, boost::recursive_mutex, boost::shared_mutex , std::recursive_mutex
, boost::mutex
, boost::recursive_mutex
, boost::shared_mutex
#if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES #if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
,std::timed_mutex, std::recursive_timed_mutex, , std::timed_mutex
boost::timed_mutex, boost::recursive_timed_mutex , std::recursive_timed_mutex
, boost::timed_mutex
, boost::recursive_timed_mutex
#endif #endif
>::value }; >::value };
}; };
/** /**
* Acquires a mutex for reading by calling .lock(). The exception is * Yields true iff T has .lock_shared() and .unlock_shared() member functions.
* boost::shared_mutex, which has a special read-lock primitive called * This is done by simply enumerating the mutexes with this interface.
* .lock_shared().
*/ */
template <class T> template <class T>
typename std::enable_if< struct HasLockSharedUnlockShared {
HasLockUnlock<T>::value && !std::is_same<T, boost::shared_mutex>::value>::type enum { value = IsOneOf<T
acquireRead(T& mutex) { , boost::shared_mutex
mutex.lock(); >::value };
} };
/** /**
* Special case for boost::shared_mutex. * Acquires a mutex for reading by calling .lock().
*
* This variant is not appropriate for shared mutexes.
*/ */
template <class T> template <class T>
typename std::enable_if<std::is_same<T, boost::shared_mutex>::value>::type typename std::enable_if<
HasLockUnlock<T>::value && !HasLockSharedUnlockShared<T>::value>::type
acquireRead(T& mutex) { acquireRead(T& mutex) {
mutex.lock_shared(); mutex.lock();
} }
/** /**
* Acquires a mutex for reading with timeout by calling .timed_lock(). This * Acquires a mutex for reading by calling .lock_shared().
* applies to three of the boost mutex classes as enumerated below. *
* This variant is not appropriate for nonshared mutexes.
*/ */
template <class T> template <class T>
typename std::enable_if<std::is_same<T, boost::shared_mutex>::value, bool>::type typename std::enable_if<HasLockSharedUnlockShared<T>::value>::type
acquireRead(T& mutex, acquireRead(T& mutex) {
unsigned int milliseconds) { mutex.lock_shared();
return mutex.timed_lock_shared(boost::posix_time::milliseconds(milliseconds));
} }
/** /**
...@@ -106,6 +113,20 @@ acquireReadWrite(T& mutex) { ...@@ -106,6 +113,20 @@ acquireReadWrite(T& mutex) {
} }
#if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES #if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
/**
* Acquires a mutex for reading by calling .try_lock_shared_for(). This applies
* to boost::shared_mutex.
*/
template <class T>
typename std::enable_if<
IsOneOf<T
, boost::shared_mutex
>::value, bool>::type
acquireRead(T& mutex,
unsigned int milliseconds) {
return mutex.try_lock_shared_for(boost::chrono::milliseconds(milliseconds));
}
/** /**
* Acquires a mutex for reading and writing with timeout by calling * Acquires a mutex for reading and writing with timeout by calling
* .try_lock_for(). This applies to two of the std mutex classes as * .try_lock_for(). This applies to two of the std mutex classes as
...@@ -113,11 +134,15 @@ acquireReadWrite(T& mutex) { ...@@ -113,11 +134,15 @@ acquireReadWrite(T& mutex) {
*/ */
template <class T> template <class T>
typename std::enable_if< typename std::enable_if<
IsOneOf<T, std::timed_mutex, std::recursive_timed_mutex>::value, bool>::type IsOneOf<T
, std::timed_mutex
, std::recursive_timed_mutex
>::value, bool>::type
acquireReadWrite(T& mutex, acquireReadWrite(T& mutex,
unsigned int milliseconds) { unsigned int milliseconds) {
// work around try_lock_for bug in some gcc versions, see // work around try_lock_for bug in some gcc versions, see
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562
// TODO: Fixed in gcc-4.9.0.
return mutex.try_lock() return mutex.try_lock()
|| (milliseconds > 0 && || (milliseconds > 0 &&
mutex.try_lock_until(std::chrono::system_clock::now() + mutex.try_lock_until(std::chrono::system_clock::now() +
...@@ -126,16 +151,19 @@ acquireReadWrite(T& mutex, ...@@ -126,16 +151,19 @@ acquireReadWrite(T& mutex,
/** /**
* Acquires a mutex for reading and writing with timeout by calling * Acquires a mutex for reading and writing with timeout by calling
* .timed_lock(). This applies to three of the boost mutex classes as * .try_lock_for(). This applies to three of the boost mutex classes as
* enumerated below. * enumerated below.
*/ */
template <class T> template <class T>
typename std::enable_if< typename std::enable_if<
IsOneOf<T, boost::shared_mutex, boost::timed_mutex, IsOneOf<T
boost::recursive_timed_mutex>::value, bool>::type , boost::shared_mutex
, boost::timed_mutex
, boost::recursive_timed_mutex
>::value, bool>::type
acquireReadWrite(T& mutex, acquireReadWrite(T& mutex,
unsigned int milliseconds) { unsigned int milliseconds) {
return mutex.timed_lock(boost::posix_time::milliseconds(milliseconds)); return mutex.try_lock_for(boost::chrono::milliseconds(milliseconds));
} }
#endif // FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES #endif // FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
...@@ -146,7 +174,7 @@ acquireReadWrite(T& mutex, ...@@ -146,7 +174,7 @@ acquireReadWrite(T& mutex,
*/ */
template <class T> template <class T>
typename std::enable_if< typename std::enable_if<
HasLockUnlock<T>::value && !std::is_same<T, boost::shared_mutex>::value>::type HasLockUnlock<T>::value && !HasLockSharedUnlockShared<T>::value>::type
releaseRead(T& mutex) { releaseRead(T& mutex) {
mutex.unlock(); mutex.unlock();
} }
...@@ -155,7 +183,7 @@ releaseRead(T& mutex) { ...@@ -155,7 +183,7 @@ releaseRead(T& mutex) {
* Special case for boost::shared_mutex. * Special case for boost::shared_mutex.
*/ */
template <class T> template <class T>
typename std::enable_if<std::is_same<T, boost::shared_mutex>::value>::type typename std::enable_if<HasLockSharedUnlockShared<T>::value>::type
releaseRead(T& mutex) { releaseRead(T& mutex) {
mutex.unlock_shared(); mutex.unlock_shared();
} }
...@@ -454,8 +482,10 @@ struct Synchronized { ...@@ -454,8 +482,10 @@ struct Synchronized {
acquire(); acquire();
} }
ConstLockedPtr(const Synchronized* parent, unsigned int milliseconds) { ConstLockedPtr(const Synchronized* parent, unsigned int milliseconds) {
if (parent->mutex_.timed_lock_shared( using namespace detail;
boost::posix_time::milliseconds(milliseconds))) { if (acquireRead(
parent->mutex_,
milliseconds)) {
parent_ = parent; parent_ = parent;
return; return;
} }
......
...@@ -20,117 +20,101 @@ ...@@ -20,117 +20,101 @@
#include <folly/Synchronized.h> #include <folly/Synchronized.h>
#include <folly/RWSpinLock.h> #include <folly/RWSpinLock.h>
#include <folly/SharedMutex.h>
#include <folly/test/SynchronizedTestLib.h> #include <folly/test/SynchronizedTestLib.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
namespace {
TEST(Synchronized, Basic) { template <class Mutex>
testBasic<std::mutex>(); class SynchronizedTest : public testing::Test {};
testBasic<std::recursive_mutex>();
#ifndef __APPLE__
testBasic<std::timed_mutex>();
testBasic<std::recursive_timed_mutex>();
#endif
using SynchronizedTestTypes = testing::Types
< folly::SharedMutexReadPriority
, folly::SharedMutexWritePriority
, std::mutex
, std::recursive_mutex
#ifdef FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
, std::timed_mutex
, std::recursive_timed_mutex
#endif
, boost::mutex
, boost::recursive_mutex
#ifdef FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
, boost::timed_mutex
, boost::recursive_timed_mutex
#endif
, boost::shared_mutex
#ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_
testBasic<folly::RWTicketSpinLock32>(); , folly::RWTicketSpinLock32
, folly::RWTicketSpinLock64
#endif #endif
>;
TYPED_TEST_CASE(SynchronizedTest, SynchronizedTestTypes);
testBasic<boost::mutex>(); TYPED_TEST(SynchronizedTest, Basic) {
testBasic<boost::recursive_mutex>(); testBasic<TypeParam>();
testBasic<boost::shared_mutex>();
#ifndef __APPLE__
testBasic<boost::timed_mutex>();
testBasic<boost::recursive_timed_mutex>();
#endif
} }
TEST(Synchronized, Concurrency) { TYPED_TEST(SynchronizedTest, Concurrency) {
testConcurrency<std::mutex>(); testConcurrency<TypeParam>();
testConcurrency<std::recursive_mutex>(); }
#ifndef __APPLE__
testConcurrency<std::timed_mutex>();
testConcurrency<std::recursive_timed_mutex>();
#endif
#ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ TYPED_TEST(SynchronizedTest, DualLocking) {
testConcurrency<folly::RWTicketSpinLock32>(); testDualLocking<TypeParam>();
#endif }
testConcurrency<boost::mutex>(); TYPED_TEST(SynchronizedTest, DualLockingWithConst) {
testConcurrency<boost::recursive_mutex>(); testDualLockingWithConst<TypeParam>();
testConcurrency<boost::shared_mutex>();
#ifndef __APPLE__
testConcurrency<boost::timed_mutex>();
testConcurrency<boost::recursive_timed_mutex>();
#endif
} }
TYPED_TEST(SynchronizedTest, ConstCopy) {
testConstCopy<TypeParam>();
}
TEST(Synchronized, DualLocking) { template <class Mutex>
testDualLocking<std::mutex>(); class SynchronizedTimedTest : public testing::Test {};
testDualLocking<std::recursive_mutex>();
#ifndef __APPLE__ using SynchronizedTimedTestTypes = testing::Types
testDualLocking<std::timed_mutex>(); < folly::SharedMutexReadPriority
testDualLocking<std::recursive_timed_mutex>(); , folly::SharedMutexWritePriority
#ifdef FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
, std::timed_mutex
, std::recursive_timed_mutex
, boost::timed_mutex
, boost::recursive_timed_mutex
, boost::shared_mutex
#endif #endif
#ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_
testDualLocking<folly::RWTicketSpinLock32>(); , folly::RWTicketSpinLock32
, folly::RWTicketSpinLock64
#endif #endif
>;
TYPED_TEST_CASE(SynchronizedTimedTest, SynchronizedTimedTestTypes);
testDualLocking<boost::mutex>(); TYPED_TEST(SynchronizedTimedTest, TimedSynchronized) {
testDualLocking<boost::recursive_mutex>(); testTimedSynchronized<TypeParam>();
testDualLocking<boost::shared_mutex>();
#ifndef __APPLE__
testDualLocking<boost::timed_mutex>();
testDualLocking<boost::recursive_timed_mutex>();
#endif
} }
template <class Mutex>
class SynchronizedTimedWithConstTest : public testing::Test {};
TEST(Synchronized, DualLockingWithConst) { using SynchronizedTimedWithConstTestTypes = testing::Types
testDualLockingWithConst<std::mutex>(); < folly::SharedMutexReadPriority
testDualLockingWithConst<std::recursive_mutex>(); , folly::SharedMutexWritePriority
#ifndef __APPLE__ #ifdef FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
testDualLockingWithConst<std::timed_mutex>(); , boost::shared_mutex
testDualLockingWithConst<std::recursive_timed_mutex>();
#endif #endif
#ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_
testDualLockingWithConst<folly::RWTicketSpinLock32>(); , folly::RWTicketSpinLock32
, folly::RWTicketSpinLock64
#endif #endif
>;
TYPED_TEST_CASE(
SynchronizedTimedWithConstTest, SynchronizedTimedWithConstTestTypes);
testDualLockingWithConst<boost::mutex>(); TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) {
testDualLockingWithConst<boost::recursive_mutex>(); testTimedSynchronizedWithConst<TypeParam>();
testDualLockingWithConst<boost::shared_mutex>();
#ifndef __APPLE__
testDualLockingWithConst<boost::timed_mutex>();
testDualLockingWithConst<boost::recursive_timed_mutex>();
#endif
} }
#ifndef __APPLE__
TEST(Synchronized, TimedSynchronized) {
testTimedSynchronized<std::timed_mutex>();
testTimedSynchronized<std::recursive_timed_mutex>();
testTimedSynchronized<boost::timed_mutex>();
testTimedSynchronized<boost::recursive_timed_mutex>();
testTimedSynchronized<boost::shared_mutex>();
testTimedSynchronizedWithConst<boost::shared_mutex>();
}
#endif
TEST(Synchronized, ConstCopy) {
#ifndef __APPLE__
testConstCopy<std::timed_mutex>();
testConstCopy<std::recursive_timed_mutex>();
testConstCopy<boost::timed_mutex>();
testConstCopy<boost::recursive_timed_mutex>();
#endif
testConstCopy<boost::shared_mutex>();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment