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.
16 #include <folly/SynchronizedPtr.h>
18 #include <folly/Optional.h>
19 #include <folly/Replaceable.h>
20 #include <folly/portability/GTest.h>
21 #include <folly/synchronization/RWSpinLock.h>
23 template <typename SPtr>
24 void basics(SPtr& sptr) {
25 EXPECT_TRUE((std::is_same<int const&, decltype(*sptr.rlock())>::value));
26 auto initialValue = *sptr.rlock();
27 bool rlockedTypeOK{false};
28 sptr.withRLock([&](auto&& value) {
29 rlockedTypeOK = std::is_same<int const&, decltype(value)>::value;
31 EXPECT_TRUE(rlockedTypeOK);
32 EXPECT_TRUE((std::is_same<int&, decltype(*sptr.wlock())>::value));
33 bool wlockedTypeOK{false};
34 sptr.withWLock([&](auto&& value) {
35 wlockedTypeOK = std::is_same<int&, decltype(value)>::value;
38 EXPECT_TRUE(wlockedTypeOK);
39 EXPECT_EQ(initialValue + 1, *sptr.rlock());
42 TEST(SynchronizedPtrTest, Shared) {
43 folly::SynchronizedPtr<std::shared_ptr<int>> pInt{std::make_shared<int>(0)};
47 TEST(SynchronizedPtrTest, UniqueBasic) {
48 folly::SynchronizedPtr<std::unique_ptr<int>> pInt{std::make_unique<int>(0)};
52 TEST(SynchronizedPtrTest, UniqueDeleter) {
53 bool calledDeleter = false;
54 auto x = [&](int* ptr) {
59 folly::SynchronizedPtr<std::unique_ptr<int, decltype(x)>> pInt{
60 std::unique_ptr<int, decltype(x)>(new int(0), x)};
62 EXPECT_TRUE((std::is_same<
63 std::unique_ptr<int, decltype(x)>&,
64 decltype(*pInt.wlockPointer())>::value));
65 pInt.wlockPointer()->reset(new int(5));
66 EXPECT_TRUE(calledDeleter);
67 calledDeleter = false;
69 EXPECT_TRUE(calledDeleter);
72 TEST(SynchronizedPtrTest, Replaceable) {
73 folly::SynchronizedPtr<folly::Replaceable<int>> pInt{0};
74 folly::SynchronizedPtr<folly::Replaceable<int const>> pcInt{2};
77 (std::is_same<folly::Replaceable<int>&, decltype(*pInt.wlockPointer())>::
79 EXPECT_TRUE((std::is_same<
80 folly::Replaceable<int const>&,
81 decltype(*pcInt.wlockPointer())>::value));
82 pcInt.withWLockPointer([](auto&& ptr) {
84 (std::is_same<folly::Replaceable<int const>&, decltype(ptr)>::value));
87 EXPECT_EQ(4, *pcInt.rlock());
90 TEST(SynchronizedPtrTest, Optional) {
91 folly::SynchronizedPtr<folly::Optional<int>, folly::RWSpinLock> pInt{0};
94 (std::is_same<folly::Optional<int>&, decltype(*pInt.wlockPointer())>::
96 EXPECT_TRUE(static_cast<bool>(pInt.rlock()));
97 pInt.withWLockPointer([](auto&& ptr) {
98 EXPECT_TRUE((std::is_same<folly::Optional<int>&, decltype(ptr)>::value));
101 EXPECT_FALSE(static_cast<bool>(pInt.rlock()));
104 TEST(SynchronizedPtrTest, Virtual) {
106 virtual void poke(bool&) const {}
107 virtual ~A() = default;
110 void poke(bool& b) const override {
114 folly::SynchronizedPtr<A*> pA{new B()};
115 bool itWorks = false;
116 pA.rlock()->poke(itWorks);
117 EXPECT_TRUE(itWorks);
119 pA.wlock()->poke(itWorks);
120 EXPECT_TRUE(itWorks);
121 pA.withWLockPointer([](auto&& ptr) {
122 EXPECT_TRUE((std::is_same<A*&, decltype(ptr)>::value));
127 auto lockedPtr = pA.wlockPointer();
128 EXPECT_TRUE((std::is_same<A*&, decltype(*lockedPtr)>::value));
130 *lockedPtr = new B();
133 pA.wlock()->poke(itWorks);
134 EXPECT_TRUE(itWorks);
135 delete *pA.wlockPointer();