Commit dc4e8512 authored by Aaryaman Sagar's avatar Aaryaman Sagar Committed by Facebook Github Bot

Add missing LockedPtr template constructor

Summary:
`LockedPtr`s were not constructible from other `LockedPtr`s with different
lock policies even if their unlock policies were the same.

Fix that.

Reviewed By: simpkins

Differential Revision: D8722292

fbshipit-source-id: bf17f86bef9ceb8e994a2bd01e66d61dbd51bb12
parent 40fb25b3
......@@ -1330,6 +1330,12 @@ class LockedPtr : public LockedPtrBase<
using UnlockerData = typename Base::UnlockerData;
// CDataType is the DataType with the appropriate const-qualification
using CDataType = detail::SynchronizedDataType<SynchronizedType>;
// Enable only if the unlock policy of the other LockPolicy is the same as
// ours
template <typename LockPolicyOther>
using EnableIfSameUnlockPolicy = std::enable_if_t<std::is_same<
typename LockPolicy::UnlockPolicy,
typename LockPolicyOther::UnlockPolicy>::value>;
// friend other LockedPtr types
template <typename SynchronizedTypeOther, typename LockPolicyOther>
......@@ -1371,19 +1377,19 @@ class LockedPtr : public LockedPtrBase<
* Move constructor.
*/
LockedPtr(LockedPtr&& rhs) noexcept = default;
template <
typename LockPolicyType,
EnableIfSameUnlockPolicy<LockPolicyType>* = nullptr>
LockedPtr(LockedPtr<SynchronizedType, LockPolicyType>&& other) noexcept
: Base{std::move(other)} {}
/**
* Move assignment operator.
*/
LockedPtr& operator=(LockedPtr&& rhs) noexcept = default;
template <
typename LockPolicyType,
typename std::enable_if<
std::is_same<
typename LockPolicy::UnlockPolicy,
typename LockPolicyType::UnlockPolicy>::value,
int>::type = 0>
EnableIfSameUnlockPolicy<LockPolicyType>* = nullptr>
LockedPtr& operator=(
LockedPtr<SynchronizedType, LockPolicyType>&& other) noexcept {
Base::operator=(std::move(other));
......
......@@ -768,97 +768,102 @@ TEST_F(SynchronizedLockTest, TestTryULock) {
template <typename LockPolicy>
using LPtr = LockedPtr<Synchronized<int>, LockPolicy>;
TEST_F(SynchronizedLockTest, TestLockedPtrCompatibilityExclusive) {
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
namespace {
template <template <typename...> class Trait>
void testLockedPtrCompatibilityExclusive() {
EXPECT_TRUE((
Trait<LPtr<LockPolicyExclusive>, LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_TRUE((Trait<
LPtr<LockPolicyExclusive>,
LPtr<LockPolicyFromUpgradeToExclusive>&&>::value));
EXPECT_FALSE((
std::is_assignable<LPtr<LockPolicyExclusive>&, LPtr<LockPolicyShared>&&>::
value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
LPtr<LockPolicyTryShared>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
LPtr<LockPolicyUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
EXPECT_FALSE(
(Trait<LPtr<LockPolicyExclusive>&, LPtr<LockPolicyShared>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyExclusive>, LPtr<LockPolicyTryShared>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyExclusive>, LPtr<LockPolicyUpgrade>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyExclusive>, LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_FALSE((Trait<
LPtr<LockPolicyExclusive>,
LPtr<LockPolicyFromExclusiveToUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
EXPECT_FALSE((Trait<
LPtr<LockPolicyExclusive>,
LPtr<LockPolicyFromExclusiveToShared>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyExclusive>&,
LPtr<LockPolicyFromUpgradeToShared>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyExclusive>, LPtr<LockPolicyFromUpgradeToShared>&&>::
value));
}
TEST_F(SynchronizedLockTest, TestLockedPtrCompatibilityShared) {
template <template <typename...> class Trait>
void testLockedPtrCompatibilityShared() {
EXPECT_TRUE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyTryShared>&&>::value));
EXPECT_TRUE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyFromUpgradeToShared>&&>::
value));
EXPECT_TRUE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyFromExclusiveToShared>&&>::
value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyExclusive>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyUpgrade>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyFromExclusiveToUpgrade>&&>::
value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyShared>, LPtr<LockPolicyFromUpgradeToExclusive>&&>::
value));
}
template <template <typename...> class Trait>
void testLockedPtrCompatibilityUpgrade() {
EXPECT_TRUE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_TRUE((
std::is_assignable<LPtr<LockPolicyShared>&, LPtr<LockPolicyTryShared>&&>::
Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyFromExclusiveToUpgrade>&&>::
value));
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyFromUpgradeToShared>&&>::value));
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyFromExclusiveToShared>&&>::value));
EXPECT_FALSE((
std::is_assignable<LPtr<LockPolicyShared>&, LPtr<LockPolicyExclusive>&&>::
value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_FALSE(
(std::is_assignable<LPtr<LockPolicyShared>&, LPtr<LockPolicyUpgrade>&&>::
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyExclusive>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyShared>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyTryShared>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyFromExclusiveToShared>&&>::
value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyFromExclusiveToUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyShared>&,
LPtr<LockPolicyFromUpgradeToExclusive>&&>::value));
EXPECT_FALSE(
(Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyFromUpgradeToShared>&&>::
value));
EXPECT_FALSE((
Trait<LPtr<LockPolicyUpgrade>, LPtr<LockPolicyFromUpgradeToExclusive>&&>::
value));
}
} // namespace
TEST_F(SynchronizedLockTest, TestLockedPtrCompatibilityExclusive) {
testLockedPtrCompatibilityExclusive<std::is_assignable>();
testLockedPtrCompatibilityExclusive<std::is_constructible>();
}
TEST_F(SynchronizedLockTest, TestLockedPtrCompatibilityShared) {
testLockedPtrCompatibilityShared<std::is_assignable>();
testLockedPtrCompatibilityShared<std::is_constructible>();
}
TEST_F(SynchronizedLockTest, TestLockedPtrCompatibilityUpgrade) {
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyTryUpgrade>&&>::value));
EXPECT_TRUE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyFromExclusiveToUpgrade>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyExclusive>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyTryExclusive>&&>::value));
EXPECT_FALSE(
(std::is_assignable<LPtr<LockPolicyUpgrade>&, LPtr<LockPolicyShared>&&>::
value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyTryShared>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyFromExclusiveToShared>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyFromUpgradeToShared>&&>::value));
EXPECT_FALSE((std::is_assignable<
LPtr<LockPolicyUpgrade>&,
LPtr<LockPolicyFromUpgradeToExclusive>&&>::value));
testLockedPtrCompatibilityUpgrade<std::is_assignable>();
testLockedPtrCompatibilityUpgrade<std::is_constructible>();
}
TEST_F(SynchronizedLockTest, TestConvertTryLockToLock) {
......
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