2 * Copyright 2014 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 #ifndef FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H
18 #define FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H
20 #include <gtest/gtest.h>
27 #include <glog/logging.h>
28 #include <folly/Foreach.h>
29 #include <folly/Random.h>
30 #include <folly/Synchronized.h>
33 static const auto seed = folly::randomNumberSeed();
34 typedef std::mt19937 RandomT;
35 static RandomT rng(seed);
37 template <class Integral1, class Integral2>
38 Integral2 random(Integral1 low, Integral2 up) {
39 std::uniform_int_distribution<> range(low, up);
43 template <class Mutex>
45 folly::Synchronized<std::vector<int>, Mutex> obj;
50 EXPECT_EQ(obj2->size(), 1000);
54 EXPECT_EQ(obj.size(), 1001);
55 EXPECT_EQ(obj.back(), 10);
56 EXPECT_EQ(obj2->size(), 1000);
59 EXPECT_EQ(obj->size(), 1001);
63 SYNCHRONIZED_CONST (obj) {
64 EXPECT_EQ(obj.size(), 1001);
66 EXPECT_EQ(obj->size(), 1001);
70 SYNCHRONIZED (lockedObj, *&obj) {
71 lockedObj.front() = 2;
74 EXPECT_EQ(obj->size(), 1001);
75 EXPECT_EQ(obj->back(), 10);
76 EXPECT_EQ(obj2->size(), 1000);
78 EXPECT_EQ(FB_ARG_2_OR_1(1, 2), 2);
79 EXPECT_EQ(FB_ARG_2_OR_1(1), 1);
82 template <class Mutex> void testConcurrency() {
83 folly::Synchronized<std::vector<int>, Mutex> v;
86 static bool threadMain(int i,
87 folly::Synchronized<std::vector<int>, Mutex>& pv) {
88 usleep(::random(100 * 1000, 1000 * 1000));
93 // Aaand test the SYNCHRONIZED macro
94 SYNCHRONIZED (v, pv) {
95 v.push_back(2 * i + 1);
102 std::vector<std::thread> results;
104 static const size_t threads = 100;
105 FOR_EACH_RANGE (i, 0, threads) {
106 results.push_back(std::thread([&, i]() { Local::threadMain(i, v); }));
109 FOR_EACH (i, results) {
113 std::vector<int> result;
116 EXPECT_EQ(result.size(), 2 * threads);
117 sort(result.begin(), result.end());
119 FOR_EACH_RANGE (i, 0, 2 * threads) {
120 EXPECT_EQ(result[i], i);
124 template <class Mutex> void testDualLocking() {
125 folly::Synchronized<std::vector<int>, Mutex> v;
126 folly::Synchronized<std::map<int, int>, Mutex> m;
129 static bool threadMain(
131 folly::Synchronized<std::vector<int>, Mutex>& pv,
132 folly::Synchronized<std::map<int, int>, Mutex>& pm) {
134 usleep(::random(100 * 1000, 1000 * 1000));
137 SYNCHRONIZED_DUAL (v, pv, m, pm) {
142 SYNCHRONIZED_DUAL (m, pm, v, pv) {
152 std::vector<std::thread> results;
154 static const size_t threads = 100;
155 FOR_EACH_RANGE (i, 0, threads) {
157 std::thread([&, i]() { Local::threadMain(i, v, m); }));
160 FOR_EACH (i, results) {
164 std::vector<int> result;
167 EXPECT_EQ(result.size(), threads);
168 sort(result.begin(), result.end());
170 FOR_EACH_RANGE (i, 0, threads) {
171 EXPECT_EQ(result[i], i);
175 template <class Mutex> void testDualLockingWithConst() {
176 folly::Synchronized<std::vector<int>, Mutex> v;
177 folly::Synchronized<std::map<int, int>, Mutex> m;
180 static bool threadMain(
182 folly::Synchronized<std::vector<int>, Mutex>& pv,
183 const folly::Synchronized<std::map<int, int>, Mutex>& pm) {
185 usleep(::random(100 * 1000, 1000 * 1000));
188 SYNCHRONIZED_DUAL (v, pv, m, pm) {
193 SYNCHRONIZED_DUAL (m, pm, v, pv) {
203 std::vector<std::thread> results;
205 static const size_t threads = 100;
206 FOR_EACH_RANGE (i, 0, threads) {
208 std::thread([&, i]() { Local::threadMain(i, v, m); }));
211 FOR_EACH (i, results) {
215 std::vector<int> result;
218 EXPECT_EQ(result.size(), threads);
219 sort(result.begin(), result.end());
221 FOR_EACH_RANGE (i, 0, threads) {
222 EXPECT_EQ(result[i], i);
226 template <class Mutex> void testTimedSynchronized() {
227 folly::Synchronized<std::vector<int>, Mutex> v;
230 static bool threadMain(int i,
231 folly::Synchronized<std::vector<int>, Mutex>& pv) {
232 usleep(::random(100 * 1000, 1000 * 1000));
235 pv->push_back(2 * i);
237 // Aaand test the TIMED_SYNCHRONIZED macro
239 TIMED_SYNCHRONIZED (10, v, pv) {
241 usleep(::random(15 * 1000, 150 * 1000));
242 v->push_back(2 * i + 1);
247 usleep(::random(10 * 1000, 100 * 1000));
255 std::vector<std::thread> results;
257 static const size_t threads = 100;
258 FOR_EACH_RANGE (i, 0, threads) {
259 results.push_back(std::thread([&, i]() { Local::threadMain(i, v); }));
262 FOR_EACH (i, results) {
266 std::vector<int> result;
269 EXPECT_EQ(result.size(), 2 * threads);
270 sort(result.begin(), result.end());
272 FOR_EACH_RANGE (i, 0, 2 * threads) {
273 EXPECT_EQ(result[i], i);
277 template <class Mutex> void testTimedSynchronizedWithConst() {
278 folly::Synchronized<std::vector<int>, Mutex> v;
281 static bool threadMain(int i,
282 folly::Synchronized<std::vector<int>, Mutex>& pv) {
283 usleep(::random(100 * 1000, 1000 * 1000));
288 usleep(::random(5 * 1000, 1000 * 1000));
289 // Test TIMED_SYNCHRONIZED_CONST
291 TIMED_SYNCHRONIZED_CONST (10, v, pv) {
293 auto found = std::find(v->begin(), v->end(), i);
294 CHECK(found != v->end());
298 usleep(::random(10 * 1000, 100 * 1000));
305 std::vector<std::thread> results;
307 static const size_t threads = 100;
308 FOR_EACH_RANGE (i, 0, threads) {
309 results.push_back(std::thread([&, i]() { Local::threadMain(i, v); }));
312 FOR_EACH (i, results) {
316 std::vector<int> result;
319 EXPECT_EQ(result.size(), threads);
320 sort(result.begin(), result.end());
322 FOR_EACH_RANGE (i, 0, threads) {
323 EXPECT_EQ(result[i], i);
327 template <class Mutex> void testConstCopy() {
328 std::vector<int> input = {1, 2, 3};
329 const folly::Synchronized<std::vector<int>, Mutex> v(input);
331 std::vector<int> result;
334 EXPECT_EQ(result, input);
337 EXPECT_EQ(result, input);
341 #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H */