Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <cstdlib>
00016 #include <thread>
00017 #include <type_traits>
00018
00019 #include "absl/base/attributes.h"
00020 #include "absl/base/const_init.h"
00021 #include "absl/base/internal/raw_logging.h"
00022 #include "absl/base/thread_annotations.h"
00023 #include "absl/synchronization/mutex.h"
00024 #include "absl/synchronization/notification.h"
00025
00026 namespace {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 void ThreadOne(absl::Mutex* mutex, absl::CondVar* condvar,
00042 absl::Notification* notification, bool* state) {
00043
00044 ABSL_RAW_CHECK(!notification->HasBeenNotified(), "invalid Notification");
00045 ABSL_RAW_CHECK(*state == false, "*state not initialized");
00046
00047 {
00048 absl::MutexLock lock(mutex);
00049
00050 notification->Notify();
00051 ABSL_RAW_CHECK(notification->HasBeenNotified(), "invalid Notification");
00052
00053 while (*state == false) {
00054 condvar->Wait(mutex);
00055 }
00056 }
00057 }
00058
00059 void ThreadTwo(absl::Mutex* mutex, absl::CondVar* condvar,
00060 absl::Notification* notification, bool* state) {
00061 ABSL_RAW_CHECK(*state == false, "*state not initialized");
00062
00063
00064 notification->WaitForNotification();
00065 ABSL_RAW_CHECK(notification->HasBeenNotified(), "invalid Notification");
00066 {
00067 absl::MutexLock lock(mutex);
00068 *state = true;
00069 condvar->Signal();
00070 }
00071 }
00072
00073
00074
00075
00076 void RunTests(absl::Mutex* mutex, absl::CondVar* condvar) {
00077 absl::Mutex default_mutex;
00078 absl::CondVar default_condvar;
00079 absl::Notification notification;
00080 if (!mutex) {
00081 mutex = &default_mutex;
00082 }
00083 if (!condvar) {
00084 condvar = &default_condvar;
00085 }
00086 bool state = false;
00087 std::thread thread_one(ThreadOne, mutex, condvar, ¬ification, &state);
00088 std::thread thread_two(ThreadTwo, mutex, condvar, ¬ification, &state);
00089 thread_one.join();
00090 thread_two.join();
00091 }
00092
00093 void TestLocals() {
00094 absl::Mutex mutex;
00095 absl::CondVar condvar;
00096 RunTests(&mutex, &condvar);
00097 }
00098
00099
00100 ABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit);
00101 void TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); }
00102
00103
00104
00105
00106
00107
00108
00109
00110 using Function = void (*)();
00111
00112 class OnConstruction {
00113 public:
00114 explicit OnConstruction(Function fn) { fn(); }
00115 };
00116
00117 class OnDestruction {
00118 public:
00119 explicit OnDestruction(Function fn) : fn_(fn) {}
00120 ~OnDestruction() { fn_(); }
00121 private:
00122 Function fn_;
00123 };
00124
00125
00126
00127
00128 extern absl::Mutex early_const_init_mutex;
00129
00130
00131
00132 OnConstruction test_early_const_init([] {
00133 RunTests(&early_const_init_mutex, nullptr);
00134 });
00135
00136
00137
00138 ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
00139
00140
00141
00142
00143
00144
00145 extern absl::Mutex const_init_sanity_mutex;
00146 OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
00147 const_init_sanity_mutex.Lock();
00148 });
00149 ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
00150 OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
00151 const_init_sanity_mutex.AssertHeld();
00152 const_init_sanity_mutex.Unlock();
00153 });
00154
00155
00156
00157 extern absl::Mutex late_const_init_mutex;
00158
00159
00160
00161
00162 OnDestruction test_late_const_init([] {
00163 RunTests(&late_const_init_mutex, nullptr);
00164 });
00165 ABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit);
00166
00167 }
00168
00169 int main() {
00170 TestLocals();
00171 TestConstInitGlobal();
00172
00173
00174 std::exit(0);
00175 }