Fix RefCountTest and RCURefCount race
[folly.git] / folly / experimental / test / RefCountTest.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include <thread>
17
18 #include <folly/Baton.h>
19 #include <folly/experimental/RCURefCount.h>
20 #include <folly/experimental/TLRefCount.h>
21
22 #include <gtest/gtest.h>
23
24 namespace folly {
25
26 template <typename RefCount>
27 void basicTest() {
28   constexpr size_t numIters = 100000;
29   constexpr size_t numThreads = 10;
30
31   size_t got0 = 0;
32
33   RefCount count;
34
35   folly::Baton<> b;
36
37   std::vector<std::thread> ts;
38   folly::Baton<> threadBatons[numThreads];
39   for (size_t t = 0; t < numThreads; ++t) {
40     ts.emplace_back([&count, &b, &got0, numIters, t, &threadBatons]() {
41         for (size_t i = 0; i < numIters; ++i) {
42           auto ret = ++count;
43
44           EXPECT_TRUE(ret > 1);
45           if (i == 0) {
46             threadBatons[t].post();
47           }
48         }
49
50         if (t == 0) {
51           b.post();
52         }
53
54         for (size_t i = 0; i < numIters; ++i) {
55           auto ret = --count;
56
57           if (ret == 0) {
58             ++got0;
59             EXPECT_EQ(numIters - 1, i);
60           }
61         }
62       });
63   }
64
65   for (size_t t = 0; t < numThreads; ++t) {
66     threadBatons[t].wait();
67   }
68
69   b.wait();
70
71   count.useGlobal();
72   if (--count == 0) {
73     ++got0;
74   }
75
76   for (auto& t: ts) {
77     t.join();
78   }
79
80   EXPECT_EQ(1, got0);
81
82   EXPECT_EQ(0, ++count);
83   EXPECT_EQ(0, ++count);
84 }
85
86 TEST(RCURefCount, Basic) {
87   basicTest<RCURefCount>();
88 }
89
90 TEST(TLRefCount, Basic) {
91   basicTest<TLRefCount>();
92 }
93
94 }