2 * Copyright 2016 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/RCURefCount.h>
27 #include <folly/experimental/ReadMostlySharedPtr.h>
29 using folly::ReadMostlyMainPtr;
30 using folly::ReadMostlyWeakPtr;
31 using folly::ReadMostlySharedPtr;
33 // send SIGALRM to test process after this many seconds
34 const unsigned int TEST_TIMEOUT = 10;
36 class ReadMostlySharedPtrTest : public ::testing::Test {
38 ReadMostlySharedPtrTest() {
45 std::atomic<int>& counter;
47 TestObject(int value, std::atomic<int>& counter)
48 : value(value), counter(counter) {
53 assert(counter.load() > 0);
58 // One side calls requestAndWait(), the other side calls waitForRequest(),
59 // does something and calls completed().
62 void requestAndWait() {
64 completeBaton_.wait();
67 void waitForRequest() {
68 folly::RCURegisterThread();
73 completeBaton_.post();
77 folly::Baton<> requestBaton_;
78 folly::Baton<> completeBaton_;
81 TEST_F(ReadMostlySharedPtrTest, BasicStores) {
82 ReadMostlyMainPtr<TestObject> ptr;
85 std::atomic<int> cnt1{0};
86 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
87 EXPECT_EQ(1, cnt1.load());
89 // Store 2, check that 1 is destroyed.
90 std::atomic<int> cnt2{0};
91 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
92 EXPECT_EQ(1, cnt2.load());
93 EXPECT_EQ(0, cnt1.load());
95 // Store nullptr, check that 2 is destroyed.
97 EXPECT_EQ(0, cnt2.load());
100 TEST_F(ReadMostlySharedPtrTest, BasicLoads) {
101 std::atomic<int> cnt2{0};
102 ReadMostlySharedPtr<TestObject> x;
105 ReadMostlyMainPtr<TestObject> ptr;
107 // Check that ptr is initially nullptr.
108 EXPECT_EQ(ptr.get(), nullptr);
110 std::atomic<int> cnt1{0};
111 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
112 EXPECT_EQ(1, cnt1.load());
115 EXPECT_EQ(1, x->value);
117 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
118 EXPECT_EQ(1, cnt2.load());
119 EXPECT_EQ(1, cnt1.load());
122 EXPECT_EQ(2, x->value);
123 EXPECT_EQ(0, cnt1.load());
126 EXPECT_EQ(1, cnt2.load());
129 EXPECT_EQ(1, cnt2.load());
132 EXPECT_EQ(0, cnt2.load());
135 TEST_F(ReadMostlySharedPtrTest, LoadsFromThreads) {
136 std::atomic<int> cnt{0};
139 ReadMostlyMainPtr<TestObject> ptr;
140 Coordinator loads[7];
143 loads[0].waitForRequest();
144 EXPECT_EQ(ptr.getShared(), nullptr);
145 loads[0].completed();
147 loads[3].waitForRequest();
148 EXPECT_EQ(2, ptr.getShared()->value);
149 loads[3].completed();
151 loads[4].waitForRequest();
152 EXPECT_EQ(4, ptr.getShared()->value);
153 loads[4].completed();
155 loads[5].waitForRequest();
156 EXPECT_EQ(5, ptr.getShared()->value);
157 loads[5].completed();
161 loads[1].waitForRequest();
162 EXPECT_EQ(1, ptr.getShared()->value);
163 loads[1].completed();
165 loads[2].waitForRequest();
166 EXPECT_EQ(2, ptr.getShared()->value);
167 loads[2].completed();
169 loads[6].waitForRequest();
170 EXPECT_EQ(5, ptr.getShared()->value);
171 loads[6].completed();
174 loads[0].requestAndWait();
176 ptr.reset(folly::make_unique<TestObject>(1, cnt));
177 loads[1].requestAndWait();
179 ptr.reset(folly::make_unique<TestObject>(2, cnt));
180 loads[2].requestAndWait();
181 loads[3].requestAndWait();
183 ptr.reset(folly::make_unique<TestObject>(3, cnt));
184 ptr.reset(folly::make_unique<TestObject>(4, cnt));
185 loads[4].requestAndWait();
187 ptr.reset(folly::make_unique<TestObject>(5, cnt));
188 loads[5].requestAndWait();
189 loads[6].requestAndWait();
191 EXPECT_EQ(1, cnt.load());
197 EXPECT_EQ(0, cnt.load());
200 TEST_F(ReadMostlySharedPtrTest, Ctor) {
201 std::atomic<int> cnt1{0};
203 ReadMostlyMainPtr<TestObject> ptr(
204 folly::make_unique<TestObject>(1, cnt1));
206 EXPECT_EQ(1, ptr.getShared()->value);
209 EXPECT_EQ(0, cnt1.load());
212 TEST_F(ReadMostlySharedPtrTest, ClearingCache) {
213 ReadMostlyMainPtr<TestObject> ptr;
216 std::atomic<int> cnt1{0};
217 ptr.reset(folly::make_unique<TestObject>(1, cnt1));
222 // Cache the pointer for this thread.
227 // Wait for the thread to cache pointer.
229 EXPECT_EQ(1, cnt1.load());
231 // Store 2 and check that 1 is destroyed.
232 std::atomic<int> cnt2{0};
233 ptr.reset(folly::make_unique<TestObject>(2, cnt2));
234 EXPECT_EQ(0, cnt1.load());