Skip to content

Commit

Permalink
unique_lock_guard, shared_lock_guard
Browse files Browse the repository at this point in the history
Reviewed By: iahs

Differential Revision: D31183931

fbshipit-source-id: e97fcc99bbe6271def731916321eaf081d82d942
  • Loading branch information
yfeldblum authored and facebook-github-bot committed Oct 2, 2021
1 parent 6e0b7ff commit 5b38d6f
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 6 deletions.
6 changes: 3 additions & 3 deletions folly/synchronization/DistributedMutex-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1718,13 +1718,13 @@ class unique_lock<
template <template <typename> class Atom, bool TimePublishing>
class lock_guard<
::folly::detail::distributed_mutex::DistributedMutex<Atom, TimePublishing>>
: public ::folly::lock_guard_base<
: public ::folly::unique_lock_guard_base<
::folly::detail::distributed_mutex::
DistributedMutex<Atom, TimePublishing>> {
public:
using ::folly::lock_guard_base<
using ::folly::unique_lock_guard_base<
::folly::detail::distributed_mutex::
DistributedMutex<Atom, TimePublishing>>::lock_guard_base;
DistributedMutex<Atom, TimePublishing>>::unique_lock_guard_base;
};

} // namespace std
22 changes: 19 additions & 3 deletions folly/synchronization/Lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ class upgrade_lock : public upgrade_lock_base<Mutex> {
// When defining lockable-with-state mutex types, specialize std::lock_guard
// to derive this.
template <typename Mutex>
class lock_guard_base
class unique_lock_guard_base
: public detail::lock_guard_base<Mutex, detail::lock_policy_unique> {
private:
using base = detail::lock_guard_base<Mutex, detail::lock_policy_unique>;
Expand All @@ -481,10 +481,26 @@ class lock_guard_base
using base::base;
};

// lock_guard
// unique_lock_guard
//
// Alias to std::lock_guard.
using std::lock_guard;
template <typename Mutex>
using unique_lock_guard = std::lock_guard<Mutex>;

// shared_lock_guard
//
// A lock-guard which holds shared locks, usable with any shared mutex type.
//
// Works with both lockable mutex types and lockable-with-state mutex types.
template <typename Mutex>
class shared_lock_guard
: public detail::lock_guard_base<Mutex, detail::lock_policy_shared> {
private:
using base = detail::lock_guard_base<Mutex, detail::lock_policy_shared>;

public:
using base::base;
};

namespace detail {

Expand Down
96 changes: 96 additions & 0 deletions folly/synchronization/test/LockTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ class shared_lock<Mutex<X, S, U>>
using folly::shared_lock_base<Mutex<X, S, U>>::shared_lock_base;
};

template <typename X, typename S, typename U>
class lock_guard<Mutex<X, S, U>>
: public folly::unique_lock_guard_base<Mutex<X, S, U>> {
using folly::unique_lock_guard_base<Mutex<X, S, U>>::unique_lock_guard_base;
};

} // namespace std

// general helpers for use across test types
Expand Down Expand Up @@ -340,6 +346,27 @@ using s = folly::shared_lock<M>;
template <typename M>
using u = folly::upgrade_lock<M>;

template <typename M>
using xg = folly::unique_lock_guard<M>;
template <typename M>
using sg = folly::shared_lock_guard<M>;

template <typename>
struct lock_guard_lock_t_;
template <typename M>
struct lock_guard_lock_t_<folly::unique_lock_guard<M>> {
using type = folly::unique_lock<M>;
};
template <typename M>
struct lock_guard_lock_t_<folly::shared_lock_guard<M>> {
using type = folly::shared_lock<M>;
};
template <typename LG>
using lock_guard_lock_t = typename lock_guard_lock_t_<LG>::type;
template <typename LG>
using lock_guard_state_t =
folly::detail::lock_state_type_of_t<lock_guard_lock_t<LG>>;

// combinatorial test suite for lock types
//
// combinations:
Expand Down Expand Up @@ -880,6 +907,75 @@ INSTANTIATE_TYPED_TEST_SUITE_P(
INSTANTIATE_TYPED_TEST_SUITE_P(
U, LockTest, decltype(LockTestParam<0, 0, 1, u>{}));

// combinatorial test suite for lock guard types
//
// combinations:
// - lock is: x (unique), s (shared)
// - lock has state?
//
// lower x, s denote locks sans state
// upper X, S denote locks with state

template <int X, int S, int U, template <typename> class L>
struct LockGuardTestParam {
using unique_lock_state = std::conditional_t<X, UniqueLockState, void>;
using shared_lock_state = std::conditional_t<S, SharedLockState, void>;
using upgrade_lock_state = std::conditional_t<U, UpgradeLockState, void>;
template <typename M>
using lock_type = L<M>;
};

template <typename Param>
struct LockGuardTest : testing::TestWithParam<Param> {};
TYPED_TEST_SUITE_P(LockGuardTest);

TYPED_TEST_P(LockGuardTest, construct_mutex) {
using mutex_type = param_mutex_t<TypeParam>;
using lock_guard_type = param_lock_t<TypeParam>;

mutex_type m;
{
lock_guard_type l{m};
EXPECT_EQ(held_v<lock_guard_lock_t<lock_guard_type>>, m.held);
}
EXPECT_EQ(Held::None, m.held);
}

TYPED_TEST_P(LockGuardTest, construct_mutex_adopt) {
using mutex_type = param_mutex_t<TypeParam>;
using lock_guard_type = param_lock_t<TypeParam>;
using state_type = lock_guard_state_t<lock_guard_type>;

mutex_type m;
m.held = held_v<lock_guard_lock_t<lock_guard_type>>;
m.locked_until = m.now + 1s;
{
lock_guard_type l = std::invoke([&] {
if constexpr (std::is_void_v<state_type>) {
return lock_guard_type{m, std::adopt_lock};
} else {
return lock_guard_type{m, std::adopt_lock, state_type{true}};
}
});
EXPECT_EQ(held_v<lock_guard_lock_t<lock_guard_type>>, m.held);
}
EXPECT_EQ(Held::None, m.held);
}

REGISTER_TYPED_TEST_SUITE_P(
LockGuardTest, //
construct_mutex,
construct_mutex_adopt);

INSTANTIATE_TYPED_TEST_SUITE_P(
x, LockGuardTest, decltype(LockGuardTestParam<0, 0, 0, xg>{}));
INSTANTIATE_TYPED_TEST_SUITE_P(
X, LockGuardTest, decltype(LockGuardTestParam<1, 0, 0, xg>{}));
INSTANTIATE_TYPED_TEST_SUITE_P(
s, LockGuardTest, decltype(LockGuardTestParam<0, 0, 0, sg>{}));
INSTANTIATE_TYPED_TEST_SUITE_P(
S, LockGuardTest, decltype(LockGuardTestParam<0, 1, 0, sg>{}));

// combinatorial test suite for lock transitions
//
// combinations:
Expand Down

0 comments on commit 5b38d6f

Please sign in to comment.