proxygen
RcuTest.cpp File Reference
#include <folly/synchronization/Rcu.h>
#include <thread>
#include <vector>
#include <glog/logging.h>
#include <folly/Benchmark.h>
#include <folly/Random.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/GTest.h>

Go to the source code of this file.

Classes

class  des
 

Functions

 DEFINE_int64 (iters, 100000,"Number of iterations")
 
 DEFINE_uint64 (threads, 32,"Number of threads")
 
 TEST (RcuTest, Basic)
 
 TEST (RcuTest, Guard)
 
 TEST (RcuTest, Perf)
 
 TEST (RcuTest, ResetPerf)
 
 TEST (RcuTest, SlowReader)
 
rcu_reader tryretire (des *obj)
 
 TEST (RcuTest, CopyGuard)
 
 TEST (RcuTest, Stress)
 
 TEST (RcuTest, Synchronize)
 
 TEST (RcuTest, NewDomainTest)
 
 TEST (RcuTest, NewDomainGuardTest)
 
 TEST (RcuTest, MovableReader)
 
 TEST (RcuTest, SynchronizeInCall)
 
 TEST (RcuTest, MoveReaderBetweenThreads)
 
 TEST (RcuTest, ForkTest)
 
 TEST (RcuTest, ThreadLocalList)
 
 TEST (RcuTest, ThreadDeath)
 
 TEST (RcuTest, RcuObjBase)
 

Function Documentation

DEFINE_int64 ( iters  ,
100000  ,
"Number of iterations"   
)
DEFINE_uint64 ( threads  ,
32  ,
"Number of threads  
)
TEST ( RcuTest  ,
Basic   
)

Definition at line 33 of file RcuTest.cpp.

References folly::rcu_retire().

33  {
34  auto foo = new int(2);
35  rcu_retire(foo);
36 }
void rcu_retire(T *p, D d={}, rcu_domain< Tag > *domain=rcu_default_domain())
Definition: Rcu.h:466
TEST ( RcuTest  ,
Guard   
)

Definition at line 48 of file RcuTest.cpp.

References EXPECT_TRUE, g(), folly::rcu_retire(), and folly::synchronize_rcu().

48  {
49  bool del = false;
50  auto foo = new des(&del);
51  { rcu_reader g; }
52  rcu_retire(foo);
54  EXPECT_TRUE(del);
55 }
Definition: RcuTest.cpp:38
void rcu_retire(T *p, D d={}, rcu_domain< Tag > *domain=rcu_default_domain())
Definition: Rcu.h:466
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
g_t g(f_t)
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
Perf   
)

Definition at line 57 of file RcuTest.cpp.

References count, diff(), g(), i, now(), and start.

57  {
58  long i = FLAGS_iters;
60  while (i-- > 0) {
61  rcu_reader g;
62  }
64  printf(
65  "Total time %li ns \n",
66  std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count() /
67  FLAGS_iters);
68 }
std::chrono::steady_clock::time_point now()
auto start
int * count
uint64_t diff(uint64_t a, uint64_t b)
Definition: FutexTest.cpp:135
g_t g(f_t)
TEST ( RcuTest  ,
ResetPerf   
)

Definition at line 70 of file RcuTest.cpp.

References count, diff(), i, now(), and start.

70  {
71  long i = FLAGS_iters;
73  while (i-- > 0) {
74  rcu_retire<int>(nullptr, [](int*) {});
75  }
77  printf(
78  "Total time %li ns \n",
79  std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count() /
80  FLAGS_iters);
81 }
std::chrono::steady_clock::time_point now()
auto start
int * count
uint64_t diff(uint64_t a, uint64_t b)
Definition: FutexTest.cpp:135
TEST ( RcuTest  ,
SlowReader   
)

Definition at line 83 of file RcuTest.cpp.

References g(), folly::synchronize_rcu(), and folly::pushmi::detail::t.

83  {
84  std::thread t;
85  {
86  rcu_reader g;
87 
88  t = std::thread([&]() { synchronize_rcu(); });
89  usleep(100); // Wait for synchronize to start
90  }
91  t.join();
92 }
g_t g(f_t)
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
CopyGuard   
)

Definition at line 100 of file RcuTest.cpp.

References EXPECT_FALSE, EXPECT_TRUE, folly::rcu_barrier(), and tryretire().

100  {
101  bool del = false;
102  auto foo = new des(&del);
103  {
104  auto res = tryretire(foo);
105  EXPECT_FALSE(del);
106  }
107  rcu_barrier();
108  EXPECT_TRUE(del);
109 }
Definition: RcuTest.cpp:38
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void rcu_barrier(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:456
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
rcu_reader tryretire(des *obj)
Definition: RcuTest.cpp:94
TEST ( RcuTest  ,
Stress   
)

Definition at line 111 of file RcuTest.cpp.

References EXPECT_EQ, g(), i, folly::Random::rand32(), sum(), folly::synchronize_rcu(), folly::pushmi::detail::t, threads, and uint32_t.

111  {
112  std::vector<std::thread> threads;
113  constexpr uint32_t sz = 1000;
114  std::atomic<int*> ints[sz];
115  for (uint32_t i = 0; i < sz; i++) {
116  ints[i].store(new int(0));
117  }
118  for (unsigned th = 0; th < FLAGS_threads; th++) {
119  threads.push_back(std::thread([&]() {
120  for (int i = 0; i < FLAGS_iters / 100; i++) {
121  rcu_reader g;
122  int sum = 0;
123  int* ptrs[sz];
124  for (uint32_t j = 0; j < sz; j++) {
125  ptrs[j] = ints[j].load(std::memory_order_acquire);
126  }
127  for (uint32_t j = 0; j < sz; j++) {
128  sum += *ptrs[j];
129  }
130  EXPECT_EQ(sum, 0);
131  }
132  }));
133  }
134  std::atomic<bool> done{false};
135  std::thread updater([&]() {
136  while (!done.load()) {
137  auto newint = new int(0);
138  auto oldint = ints[folly::Random::rand32() % sz].exchange(newint);
139  rcu_retire<int>(oldint, [](int* obj) {
140  *obj = folly::Random::rand32();
141  delete obj;
142  });
143  }
144  });
145  for (auto& t : threads) {
146  t.join();
147  }
148  done = true;
149  updater.join();
150  // Cleanup for asan
151  synchronize_rcu();
152  for (uint32_t i = 0; i < sz; i++) {
153  delete ints[i].exchange(nullptr);
154  }
155 }
std::atomic< int64_t > sum(0)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::vector< std::thread::id > threads
g_t g(f_t)
static uint32_t rand32()
Definition: Random.h:213
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
Synchronize   
)

Definition at line 157 of file RcuTest.cpp.

References i, folly::synchronize_rcu(), folly::pushmi::detail::t, and threads.

157  {
158  std::vector<std::thread> threads;
159  for (unsigned th = 0; th < FLAGS_threads; th++) {
160  threads.push_back(std::thread([&]() {
161  for (int i = 0; i < 10; i++) {
162  synchronize_rcu();
163  }
164  }));
165  }
166  for (auto& t : threads) {
167  t.join();
168  }
169 }
std::vector< std::thread::id > threads
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
NewDomainTest   
)

Definition at line 171 of file RcuTest.cpp.

References folly::synchronize_rcu().

171  {
172  struct UniqueTag;
173  rcu_domain<UniqueTag> newdomain(nullptr);
174  synchronize_rcu(&newdomain);
175 }
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
NewDomainGuardTest   
)

Definition at line 177 of file RcuTest.cpp.

References EXPECT_TRUE, g(), folly::rcu_retire(), and folly::synchronize_rcu().

177  {
178  struct UniqueTag;
179  rcu_domain<UniqueTag> newdomain(nullptr);
180  bool del = false;
181  auto foo = new des(&del);
182  { rcu_reader_domain<UniqueTag> g(&newdomain); }
183  rcu_retire(foo, {}, &newdomain);
184  synchronize_rcu(&newdomain);
185  EXPECT_TRUE(del);
186 }
Definition: RcuTest.cpp:38
void rcu_retire(T *p, D d={}, rcu_domain< Tag > *domain=rcu_default_domain())
Definition: Rcu.h:466
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
g_t g(f_t)
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
MovableReader   
)

Definition at line 188 of file RcuTest.cpp.

References f, g(), folly::gen::move, and folly::synchronize_rcu().

188  {
189  {
190  rcu_reader g;
191  rcu_reader f(std::move(g));
192  }
193  synchronize_rcu();
194  {
195  rcu_reader g(std::defer_lock);
196  rcu_reader f;
197  g = std::move(f);
198  }
199  synchronize_rcu();
200 }
auto f
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
g_t g(f_t)
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
SynchronizeInCall   
)

Definition at line 202 of file RcuTest.cpp.

References folly::rcu_default_domain(), and folly::synchronize_rcu().

202  {
203  rcu_default_domain()->call([]() { synchronize_rcu(); });
204  synchronize_rcu();
205 }
rcu_domain< RcuTag > * rcu_default_domain()
Definition: Rcu.h:385
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
MoveReaderBetweenThreads   
)

Definition at line 207 of file RcuTest.cpp.

References f, g(), folly::gen::move, folly::synchronize_rcu(), and folly::pushmi::detail::t.

207  {
208  rcu_reader g;
209  std::thread t([f = std::move(g)] {});
210  t.join();
211  synchronize_rcu();
212 }
auto f
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
g_t g(f_t)
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
ForkTest   
)

Definition at line 214 of file RcuTest.cpp.

References EXPECT_EQ, folly::gen::move, folly::rcu_default_domain(), folly::synchronize_rcu(), folly::pushmi::detail::t, and folly::detail::distributed_mutex::wait().

214  {
215  rcu_token epoch;
216  std::thread t([&]() { epoch = rcu_default_domain()->lock_shared(); });
217  t.join();
218  auto pid = fork();
219  if (pid) {
220  // parent
221  rcu_default_domain()->unlock_shared(std::move(epoch));
222  synchronize_rcu();
223  int status;
224  auto pid2 = wait(&status);
225  EXPECT_EQ(status, 0);
226  EXPECT_EQ(pid, pid2);
227  } else {
228  // child
229  synchronize_rcu();
230  exit(0); // Do not print gtest results
231  }
232 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
rcu_domain< RcuTag > * rcu_default_domain()
Definition: Rcu.h:385
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
ThreadLocalList   
)

Definition at line 234 of file RcuTest.cpp.

References folly::detail::ThreadCachedLists< Tag >::collect(), i, bm::list, folly::detail::ThreadCachedLists< Tag >::push(), threads, and tr.

234  {
235  struct TTag;
237  std::vector<std::thread> threads{FLAGS_threads};
238  std::atomic<unsigned long> done{FLAGS_threads};
239  for (auto& tr : threads) {
240  tr = std::thread([&]() {
241  for (int i = 0; i < FLAGS_iters; i++) {
243  lists.push(node);
244  }
245  --done;
246  });
247  }
248  while (done.load() > 0) {
250  lists.collect(list);
252  delete node;
253  });
254  }
255  for (auto& thread : threads) {
256  thread.join();
257  }
258  // Run cleanup pass one more time to make ASAN happy
260  lists.collect(list);
261  list.forEach(
262  [](folly::detail::ThreadCachedLists<TTag>::Node* node) { delete node; });
263 }
std::vector< std::thread::id > threads
auto tr
Encoder::MutableCompressedList list
TEST ( RcuTest  ,
ThreadDeath   
)

Definition at line 265 of file RcuTest.cpp.

References EXPECT_TRUE, folly::rcu_retire(), folly::synchronize_rcu(), and folly::pushmi::detail::t.

265  {
266  bool del = false;
267  std::thread t([&] {
268  auto foo = new des(&del);
269  rcu_retire(foo);
270  });
271  t.join();
272  synchronize_rcu();
273  EXPECT_TRUE(del);
274 }
Definition: RcuTest.cpp:38
void rcu_retire(T *p, D d={}, rcu_domain< Tag > *domain=rcu_default_domain())
Definition: Rcu.h:466
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
TEST ( RcuTest  ,
RcuObjBase   
)

Definition at line 276 of file RcuTest.cpp.

References EXPECT_TRUE, and folly::synchronize_rcu().

276  {
277  bool retired = false;
278  struct base_test : rcu_obj_base<base_test> {
279  bool* ret_;
280  base_test(bool* ret) : ret_(ret) {}
281  ~base_test() {
282  (*ret_) = true;
283  }
284  };
285 
286  auto foo = new base_test(&retired);
287  foo->retire();
288  synchronize_rcu();
289  EXPECT_TRUE(retired);
290 }
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void synchronize_rcu(rcu_domain< Tag > *domain=rcu_default_domain()) noexcept
Definition: Rcu.h:450
rcu_reader tryretire ( des obj)

Definition at line 94 of file RcuTest.cpp.

References g(), and folly::rcu_retire().

Referenced by TEST().

94  {
95  rcu_reader g;
96  rcu_retire(obj);
97  return g;
98 }
void rcu_retire(T *p, D d={}, rcu_domain< Tag > *domain=rcu_default_domain())
Definition: Rcu.h:466
g_t g(f_t)