2 * Copyright 2017-present Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/SynchronizedPtr.h>
19 #include <folly/Optional.h>
20 #include <folly/RWSpinLock.h>
21 #include <folly/Replaceable.h>
22 #include <folly/portability/GTest.h>
24 template <typename SPtr>
25 void basics(SPtr& sptr) {
26 EXPECT_TRUE((std::is_same<int const&, decltype(*sptr.rlock())>::value));
27 auto initialValue = *sptr.rlock();
28 bool rlockedTypeOK{false};
29 sptr.withRLock([&](auto&& value) {
30 rlockedTypeOK = std::is_same<int const&, decltype(value)>::value;
32 EXPECT_TRUE(rlockedTypeOK);
33 EXPECT_TRUE((std::is_same<int&, decltype(*sptr.wlock())>::value));
34 bool wlockedTypeOK{false};
35 sptr.withWLock([&](auto&& value) {
36 wlockedTypeOK = std::is_same<int&, decltype(value)>::value;
39 EXPECT_TRUE(wlockedTypeOK);
40 EXPECT_EQ(initialValue + 1, *sptr.rlock());
43 TEST(SynchronizedPtrTest, Shared) {
44 folly::SynchronizedPtr<std::shared_ptr<int>> pInt{std::make_shared<int>(0)};
48 TEST(SynchronizedPtrTest, UniqueBasic) {
49 folly::SynchronizedPtr<std::unique_ptr<int>> pInt{std::make_unique<int>(0)};
53 TEST(SynchronizedPtrTest, UniqueDeleter) {
54 bool calledDeleter = false;
55 auto x = [&](int* ptr) {
60 folly::SynchronizedPtr<std::unique_ptr<int, decltype(x)>> pInt{
61 std::unique_ptr<int, decltype(x)>(new int(0), x)};
63 EXPECT_TRUE((std::is_same<
64 std::unique_ptr<int, decltype(x)>&,
65 decltype(*pInt.wlockPointer())>::value));
66 pInt.wlockPointer()->reset(new int(5));
67 EXPECT_TRUE(calledDeleter);
68 calledDeleter = false;
70 EXPECT_TRUE(calledDeleter);
73 TEST(SynchronizedPtrTest, Replaceable) {
74 folly::SynchronizedPtr<folly::Replaceable<int>> pInt{0};
75 folly::SynchronizedPtr<folly::Replaceable<int const>> pcInt{2};
78 (std::is_same<folly::Replaceable<int>&, decltype(*pInt.wlockPointer())>::
80 EXPECT_TRUE((std::is_same<
81 folly::Replaceable<int const>&,
82 decltype(*pcInt.wlockPointer())>::value));
83 pcInt.withWLockPointer([](auto&& ptr) {
85 (std::is_same<folly::Replaceable<int const>&, decltype(ptr)>::value));
88 EXPECT_EQ(4, *pcInt.rlock());
91 TEST(SynchronizedPtrTest, Optional) {
92 folly::SynchronizedPtr<folly::Optional<int>, folly::RWSpinLock> pInt{0};
95 (std::is_same<folly::Optional<int>&, decltype(*pInt.wlockPointer())>::
97 EXPECT_TRUE(static_cast<bool>(pInt.rlock()));
98 pInt.withWLockPointer([](auto&& ptr) {
99 EXPECT_TRUE((std::is_same<folly::Optional<int>&, decltype(ptr)>::value));
102 EXPECT_FALSE(static_cast<bool>(pInt.rlock()));
105 TEST(SynchronizedPtrTest, Virtual) {
107 virtual void poke(bool&) const {}
108 virtual ~A() = default;
111 void poke(bool& b) const override {
115 folly::SynchronizedPtr<A*> pA{new B()};
116 bool itWorks = false;
117 pA.rlock()->poke(itWorks);
118 EXPECT_TRUE(itWorks);
120 pA.wlock()->poke(itWorks);
121 EXPECT_TRUE(itWorks);
122 pA.withWLockPointer([](auto&& ptr) {
123 EXPECT_TRUE((std::is_same<A*&, decltype(ptr)>::value));
128 auto lockedPtr = pA.wlockPointer();
129 EXPECT_TRUE((std::is_same<A*&, decltype(*lockedPtr)>::value));
131 *lockedPtr = new B();
134 pA.wlock()->poke(itWorks);
135 EXPECT_TRUE(itWorks);
136 delete *pA.wlockPointer();