2 * Copyright 2015 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 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
21 #include <folly/Memory.h>
22 #include <condition_variable>
23 #include <gtest/gtest.h>
25 #include <folly/Baton.h>
26 #include <folly/experimental/ReadMostlySharedPtr.h>
28 using folly::ReadMostlyMainPtr;
29 using folly::ReadMostlyWeakPtr;
30 using folly::ReadMostlySharedPtr;
32 // send SIGALRM to test process after this many seconds
33 const unsigned int TEST_TIMEOUT = 10;
35 class ReadMostlySharedPtrTest : public ::testing::Test {
37 ReadMostlySharedPtrTest() {
44 std::atomic<int>& counter;
46 TestObject(int value, std::atomic<int>& counter)
47 : value(value), counter(counter) {
52 assert(counter.load() > 0);
57 // One side calls requestAndWait(), the other side calls waitForRequest(),
58 // does something and calls completed().
61 void requestAndWait() {
63 completeBaton_.wait();
66 void waitForRequest() {
67 folly::RCURegisterThread();
72 completeBaton_.post();
76 folly::Baton<> requestBaton_;
77 folly::Baton<> completeBaton_;
80 TEST_F(ReadMostlySharedPtrTest, BasicStores) {
81 ReadMostlyMainPtr<TestObject> ptr;
84 std::atomic<int> cnt1{0};
85 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
86 EXPECT_EQ(1, cnt1.load());
88 // Store 2, check that 1 is destroyed.
89 std::atomic<int> cnt2{0};
90 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
91 EXPECT_EQ(1, cnt2.load());
92 EXPECT_EQ(0, cnt1.load());
94 // Store nullptr, check that 2 is destroyed.
96 EXPECT_EQ(0, cnt2.load());
99 TEST_F(ReadMostlySharedPtrTest, BasicLoads) {
100 std::atomic<int> cnt2{0};
101 ReadMostlySharedPtr<TestObject> x;
104 ReadMostlyMainPtr<TestObject> ptr;
106 // Check that ptr is initially nullptr.
107 EXPECT_EQ(ptr.get(), nullptr);
109 std::atomic<int> cnt1{0};
110 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
111 EXPECT_EQ(1, cnt1.load());
114 EXPECT_EQ(1, x->value);
116 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
117 EXPECT_EQ(1, cnt2.load());
118 EXPECT_EQ(1, cnt1.load());
121 EXPECT_EQ(2, x->value);
122 EXPECT_EQ(0, cnt1.load());
125 EXPECT_EQ(1, cnt2.load());
128 EXPECT_EQ(1, cnt2.load());
131 EXPECT_EQ(0, cnt2.load());
134 TEST_F(ReadMostlySharedPtrTest, LoadsFromThreads) {
135 std::atomic<int> cnt{0};
138 ReadMostlyMainPtr<TestObject> ptr;
139 Coordinator loads[7];
142 loads[0].waitForRequest();
143 EXPECT_EQ(ptr.getShared(), nullptr);
144 loads[0].completed();
146 loads[3].waitForRequest();
147 EXPECT_EQ(2, ptr.getShared()->value);
148 loads[3].completed();
150 loads[4].waitForRequest();
151 EXPECT_EQ(4, ptr.getShared()->value);
152 loads[4].completed();
154 loads[5].waitForRequest();
155 EXPECT_EQ(5, ptr.getShared()->value);
156 loads[5].completed();
160 loads[1].waitForRequest();
161 EXPECT_EQ(1, ptr.getShared()->value);
162 loads[1].completed();
164 loads[2].waitForRequest();
165 EXPECT_EQ(2, ptr.getShared()->value);
166 loads[2].completed();
168 loads[6].waitForRequest();
169 EXPECT_EQ(5, ptr.getShared()->value);
170 loads[6].completed();
173 loads[0].requestAndWait();
175 ptr.reset(folly::make_unique<TestObject>(1, cnt));
176 loads[1].requestAndWait();
178 ptr.reset(folly::make_unique<TestObject>(2, cnt));
179 loads[2].requestAndWait();
180 loads[3].requestAndWait();
182 ptr.reset(folly::make_unique<TestObject>(3, cnt));
183 ptr.reset(folly::make_unique<TestObject>(4, cnt));
184 loads[4].requestAndWait();
186 ptr.reset(folly::make_unique<TestObject>(5, cnt));
187 loads[5].requestAndWait();
188 loads[6].requestAndWait();
190 EXPECT_EQ(1, cnt.load());
196 EXPECT_EQ(0, cnt.load());
199 TEST_F(ReadMostlySharedPtrTest, Ctor) {
200 std::atomic<int> cnt1{0};
202 ReadMostlyMainPtr<TestObject> ptr(
203 folly::make_unique<TestObject>(1, cnt1));
205 EXPECT_EQ(1, ptr.getShared()->value);
208 EXPECT_EQ(0, cnt1.load());
211 TEST_F(ReadMostlySharedPtrTest, ClearingCache) {
212 ReadMostlyMainPtr<TestObject> ptr;
215 std::atomic<int> cnt1{0};
216 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
221 // Cache the pointer for this thread.
226 // Wait for the thread to cache pointer.
228 EXPECT_EQ(1, cnt1.load());
230 // Store 2 and check that 1 is destroyed.
231 std::atomic<int> cnt2{0};
232 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
233 EXPECT_EQ(0, cnt1.load());