35 template <
class Mutex>
43 #if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 45 std::recursive_timed_mutex,
48 boost::recursive_mutex,
49 #if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 51 boost::recursive_timed_mutex,
53 #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ 54 folly::RWTicketSpinLock32,
55 folly::RWTicketSpinLock64,
62 testBasic<TypeParam>();
66 testWithLock<TypeParam>();
70 testUnlock<TypeParam>();
74 testDeprecated<TypeParam>();
78 testConcurrency<TypeParam>();
82 testAcquireLocked<TypeParam>();
86 testAcquireLockedWithConst<TypeParam>();
90 testDualLocking<TypeParam>();
94 testDualLockingWithConst<TypeParam>();
98 testConstCopy<TypeParam>();
102 testInPlaceConstruction<TypeParam>();
106 testExchange<TypeParam>();
109 template <
class Mutex>
113 #if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 115 std::recursive_timed_mutex,
117 boost::recursive_timed_mutex,
120 #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ 121 folly::RWTicketSpinLock32,
122 folly::RWTicketSpinLock64,
125 folly::SharedMutexWritePriority>;
129 testTimed<TypeParam>();
133 testTimedSynchronized<TypeParam>();
136 template <
class Mutex>
140 #if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 143 #ifdef RW_SPINLOCK_USE_X86_INTRINSIC_ 144 folly::RWTicketSpinLock32,
145 folly::RWTicketSpinLock64,
148 folly::SharedMutexWritePriority>;
154 testTimedShared<TypeParam>();
158 testTimedSynchronizedWithConst<TypeParam>();
174 return CountPair{lockCount_, unlockCount_};
209 EXPECT_EQ(this->lock_state, CurrentLockState::UNLOCKED);
210 this->lock_state = CurrentLockState::UNIQUE;
213 EXPECT_EQ(this->lock_state, CurrentLockState::UNIQUE);
214 this->lock_state = CurrentLockState::UNLOCKED;
217 EXPECT_EQ(this->lock_state, CurrentLockState::UNLOCKED);
218 this->lock_state = CurrentLockState::SHARED;
221 EXPECT_EQ(this->lock_state, CurrentLockState::SHARED);
222 this->lock_state = CurrentLockState::UNLOCKED;
225 EXPECT_EQ(this->lock_state, CurrentLockState::UNLOCKED);
230 this->lock_state = CurrentLockState::UNLOCKED;
235 this->lock_state = CurrentLockState::UNIQUE;
238 EXPECT_EQ(this->lock_state, CurrentLockState::UNIQUE);
242 EXPECT_EQ(this->lock_state, CurrentLockState::UNIQUE);
243 this->lock_state = CurrentLockState::SHARED;
247 this->lock_state = CurrentLockState::SHARED;
250 template <
class Rep,
class Period>
252 EXPECT_EQ(this->lock_state, CurrentLockState::UNLOCKED);
253 this->lock_state = CurrentLockState::UNIQUE;
257 template <
class Rep,
class Period>
259 EXPECT_EQ(this->lock_state, CurrentLockState::UNLOCKED);
264 template <
class Rep,
class Period>
266 const std::chrono::duration<Rep, Period>&) {
268 this->lock_state = CurrentLockState::UNIQUE;
289 globalAllPowerfulAssertingMutex.
lock();
292 globalAllPowerfulAssertingMutex.
unlock();
320 template <
class Rep,
class Period>
322 return globalAllPowerfulAssertingMutex.
try_lock_for(arg);
325 template <
class Rep,
class Period>
330 template <
class Rep,
class Period>
332 const std::chrono::duration<Rep, Period>& arg) {
363 struct NonCopyConstructible {
364 NonCopyConstructible(
const NonCopyConstructible&) =
delete;
365 NonCopyConstructible& operator=(
const NonCopyConstructible&) =
delete;
367 struct CopyConstructible {};
383 std::is_same<std::decay<decltype(*sync.ulock())>::
type,
int>::
value,
384 "The ulock function was not well configured, blame aary@instagram.com");
387 auto ulock = sync.ulock();
400 auto ulock = sync.ulock();
415 auto ulock = sync.ulock();
416 auto slock =
ulock.moveFromUpgradeToRead();
430 auto wlock = sync.wlock();
445 auto wlock = sync.wlock();
446 auto slock =
wlock.moveFromWriteToRead();
464 std::is_same<std::decay<decltype(*sync.ulock())>::
type,
int>::
value,
465 "The ulock function was not well configured, blame aary@instagram.com");
468 sync.withULockPtr([](
auto ulock) {
487 sync.withWLockPtr([](
auto wlock) {
506 sync.withULockPtr([](
auto ulock) {
512 auto slock =
ulock.moveFromUpgradeToRead();
525 sync.withWLockPtr([](
auto wlock) {
531 auto slock =
wlock.moveFromWriteToRead();
546 std::piecewise_construct,
547 std::forward_as_tuple(3),
548 std::forward_as_tuple(1)};
555 constexpr
auto kLockable = 1;
556 constexpr
auto kWLockable = 2;
557 constexpr
auto kRLockable = 4;
558 constexpr
auto kULockable = 8;
560 template <
int kLockableType>
563 explicit TryLockable(
575 int LockableType = kLockableType,
576 std::enable_if_t<LockableType != kLockable>* =
nullptr>
581 int LockableType = kLockableType,
582 std::enable_if_t<LockableType == kULockable>* =
nullptr>
583 void lock_upgrade() {
587 bool tryLockImpl(
int lockableMask) {
590 if (kLockableType | lockableMask) {
603 void unlockImpl(
int lockableMask) {
604 if (kLockableType | lockableMask) {
613 return tryLockImpl(kLockable | kWLockable);
615 bool try_lock_shared() {
616 return tryLockImpl(kRLockable);
618 bool try_lock_upgrade() {
619 return tryLockImpl(kULockable);
623 unlockImpl(kLockable | kWLockable);
625 void unlock_shared() {
626 unlockImpl(kLockable | kRLockable);
628 void unlock_upgrade() {
629 unlockImpl(kLockable | kULockable);
637 struct TestSharedMutex {
648 void unlock_shared() {
656 bool try_lock_shared() {
688 std::function<void()>
onLock{[] {}};
689 std::function<void()>
onUnlock{[] {}};
692 template <
int kLockable,
typename Func>
693 void testTryLock(
Func func) {
698 std::piecewise_construct,
703 auto lock = func(
synchronized);
714 std::piecewise_construct,
719 auto lock = func(
synchronized);
733 void lock_shared() {}
734 void unlock_shared() {}
751 testTryLock<kLockable>(
752 [](
auto&
synchronized) {
return synchronized.tryLock(); });
756 testTryLock<kWLockable>(
757 [](
auto&
synchronized) {
return synchronized.tryWLock(); });
761 testTryLock<kRLockable>(
762 [](
auto&
synchronized) {
return synchronized.tryRLock(); });
766 testTryLock<kULockable>(
767 [](
auto&
synchronized) {
return synchronized.tryULock(); });
770 template <
typename LockPolicy>
774 template <
template <
typename...>
class Trait>
775 void testLockedPtrCompatibilityExclusive() {
801 template <
template <
typename...>
class Trait>
802 void testLockedPtrCompatibilityShared() {
828 template <
template <
typename...>
class Trait>
829 void testLockedPtrCompatibilityUpgrade() {
857 testLockedPtrCompatibilityExclusive<std::is_assignable>();
858 testLockedPtrCompatibilityExclusive<std::is_constructible>();
862 testLockedPtrCompatibilityShared<std::is_assignable>();
863 testLockedPtrCompatibilityShared<std::is_constructible>();
867 testLockedPtrCompatibilityUpgrade<std::is_assignable>();
868 testLockedPtrCompatibilityUpgrade<std::is_constructible>();
873 auto wlock =
synchronized.wlock();
876 auto ulock =
synchronized.ulock();
880 auto value =
synchronized.withWLock([](
auto& integer) {
return integer; });
884 TEST(FollyLockTest, TestVariadicLockWithSynchronized) {
886 auto syncs = std::array<folly::Synchronized<int>, 3>{};
887 auto& one = syncs[0];
888 auto const& two = syncs[1];
889 auto& three = syncs[2];
897 auto syncs = std::array<folly::Synchronized<int, std::mutex>, 2>{};
904 TEST(FollyLockTest, TestVariadicLockWithArbitraryLockables) {
905 auto&& one = std::mutex{};
906 auto&& two = std::mutex{};
908 auto lckOne = std::unique_lock<std::mutex>{one, std::defer_lock};
909 auto lckTwo = std::unique_lock<std::mutex>{two, std::defer_lock};
915 TEST(FollyLockTest, TestVariadicLockSmartAndPoliteAlgorithm) {
916 auto one = TestMutex{};
917 auto two = TestMutex{};
918 auto three = TestMutex{};
919 auto makeReset = [&] {
928 auto reset = makeReset();
939 auto reset = makeReset();
940 two.shouldTryLockSucceed =
false;
951 auto reset = makeReset();
952 three.shouldTryLockSucceed =
false;
963 auto reset = makeReset();
964 three.shouldTryLockSucceed =
false;
968 one.shouldTryLockSucceed =
false;
970 one.onLock = [&] { three.shouldTryLockSucceed =
true; };
983 TEST(SynchronizedAlgorithmTest, Basic) {
985 auto value =
synchronized([](
auto s) {
return *
s; },
wlock(sync));
989 TEST(SynchronizedAlgorithmTest, BasicNonShareableMutex) {
991 auto value =
synchronized([](
auto s) {
return *
s; },
lock(sync));
999 std::piecewise_construct,
1001 std::make_tuple([&] { ++locked; }, [&] { ++unlocked; }, [] {}, [] {})};
1003 synchronized([](
auto) {},
wlock(sync));
1012 std::piecewise_construct,
1014 std::make_tuple([] {}, [] {}, [&] { ++locked; }, [&] { ++unlocked; })};
1016 synchronized([](
auto) {},
rlock(sync));
1026 std::piecewise_construct,
1030 std::piecewise_construct,
1034 synchronized([](
auto,
auto) {},
wlock(one),
rlock(two));
bool shouldTryLockSucceed
static void resetLockUnlockCount()
bool try_lock_upgrade_for(const std::chrono::duration< Rep, Period > &arg)
void unlock_upgrade_and_lock_shared()
auto wlock(Synchronized< D, M > &synchronized, Args &&...args)
static std::unique_ptr< SSLLock[]> & locks()
SharedMutexImpl< true > SharedMutexReadPriority
static FakeAllPowerfulAssertingMutexInternal globalAllPowerfulAssertingMutex
#define EXPECT_EQ(val1, val2)
constexpr detail::Map< Move > move
folly::Function< void()> onUnlock
NonDefaultConstructibleMutex(int valueIn)
const bool kShouldSucceed
TYPED_TEST_CASE(SynchronizedTest, SynchronizedTestTypes)
—— Concurrent Priority Queue Implementation ——
testing::Types< folly::SharedMutexReadPriority, folly::SharedMutexWritePriority > SynchronizedTimedTestTypes
auto rlock(const Synchronized< Data, Mutex > &synchronized, Args &&...args)
static FOLLY_TLS int unlockCount_
void unlock_and_lock_upgrade()
testing::Types< folly::SharedMutexReadPriority, folly::SharedMutexWritePriority, std::mutex, std::recursive_mutex, boost::mutex, boost::recursive_mutex, boost::shared_mutex, folly::SpinLock > SynchronizedTestTypes
bool try_unlock_upgrade_and_lock_for(const std::chrono::duration< Rep, Period > &arg)
TYPED_TEST(SynchronizedTest, Basic)
static FOLLY_TLS int lockCount_
std::function< void()> onUnlock_
CurrentLockState lock_state
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
void unlock_upgrade_and_lock()
std::function< void()> onLock_
folly::Function< void()> onLock
void unlock_and_lock_shared()
std::pair< int, int > CountPair
std::function< void()> onUnlockShared_
TEST_F(AsyncSSLSocketWriteTest, write_coalescing1)
bool try_lock_for(const std::chrono::duration< Rep, Period > &)
void unlock_upgrade_and_lock_shared()
#define EXPECT_TRUE(condition)
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
bool try_lock_for(const std::chrono::duration< Rep, Period > &arg)
testing::Types< folly::SharedMutexReadPriority, folly::SharedMutexWritePriority > SynchronizedTimedWithConstTestTypes
static CountPair getLockUnlockCount()
void unlock_and_lock_upgrade()
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
auto ulock(Synchronized< D, M > &synchronized, Args &&...args)
SharedMutexImpl< false > SharedMutexWritePriority
#define EXPECT_FALSE(condition)
void unlock_upgrade_and_lock()
~FakeAllPowerfulAssertingMutex()
std::function< void()> onLockShared_
TEST(SequencedExecutor, CPUThreadPoolExecutor)
void unlock_and_lock_shared()
bool try_lock_upgrade_for(const std::chrono::duration< Rep, Period > &)
bool try_unlock_upgrade_and_lock_for(const std::chrono::duration< Rep, Period > &)