Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/base/call_once.h"
00016
00017 #include <thread>
00018 #include <vector>
00019
00020 #include "gtest/gtest.h"
00021 #include "absl/base/attributes.h"
00022 #include "absl/base/const_init.h"
00023 #include "absl/base/thread_annotations.h"
00024 #include "absl/synchronization/mutex.h"
00025
00026 namespace absl {
00027 namespace {
00028
00029 absl::once_flag once;
00030
00031 ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
00032
00033 int running_thread_count GUARDED_BY(counters_mu) = 0;
00034 int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
00035 int call_once_finished_count GUARDED_BY(counters_mu) = 0;
00036 int call_once_return_count GUARDED_BY(counters_mu) = 0;
00037 bool done_blocking GUARDED_BY(counters_mu) = false;
00038
00039
00040 void WaitAndIncrement() {
00041 counters_mu.Lock();
00042 ++call_once_invoke_count;
00043 counters_mu.Unlock();
00044
00045 counters_mu.LockWhen(Condition(&done_blocking));
00046 ++call_once_finished_count;
00047 counters_mu.Unlock();
00048 }
00049
00050 void ThreadBody() {
00051 counters_mu.Lock();
00052 ++running_thread_count;
00053 counters_mu.Unlock();
00054
00055 absl::call_once(once, WaitAndIncrement);
00056
00057 counters_mu.Lock();
00058 ++call_once_return_count;
00059 counters_mu.Unlock();
00060 }
00061
00062
00063 bool ThreadsAreSetup(void*) EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
00064
00065 return running_thread_count == 10 && call_once_invoke_count == 1;
00066 }
00067
00068 TEST(CallOnceTest, ExecutionCount) {
00069 std::vector<std::thread> threads;
00070
00071
00072 for (int i = 0; i < 10; ++i) {
00073 threads.emplace_back(ThreadBody);
00074 }
00075
00076
00077
00078
00079 counters_mu.LockWhen(Condition(ThreadsAreSetup, nullptr));
00080
00081
00082
00083
00084 EXPECT_EQ(call_once_invoke_count, 1);
00085 EXPECT_EQ(call_once_finished_count, 0);
00086 EXPECT_EQ(call_once_return_count, 0);
00087
00088
00089
00090 done_blocking = true;
00091 counters_mu.Unlock();
00092
00093 for (std::thread& thread : threads) {
00094 thread.join();
00095 }
00096
00097 counters_mu.Lock();
00098 EXPECT_EQ(call_once_invoke_count, 1);
00099 EXPECT_EQ(call_once_finished_count, 1);
00100 EXPECT_EQ(call_once_return_count, 10);
00101 counters_mu.Unlock();
00102 }
00103
00104 }
00105 }