Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
00017 #define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
00018
00019 #include "absl/base/config.h"
00020
00021 #ifndef _WIN32
00022 #include <pthread.h>
00023 #endif
00024
00025 #ifdef ABSL_HAVE_SEMAPHORE_H
00026 #include <semaphore.h>
00027 #endif
00028
00029 #include <atomic>
00030 #include <cstdint>
00031
00032 #include "absl/base/internal/thread_identity.h"
00033 #include "absl/synchronization/internal/kernel_timeout.h"
00034
00035
00036 #define ABSL_WAITER_MODE_FUTEX 0
00037 #define ABSL_WAITER_MODE_SEM 1
00038 #define ABSL_WAITER_MODE_CONDVAR 2
00039 #define ABSL_WAITER_MODE_WIN32 3
00040
00041 #if defined(ABSL_FORCE_WAITER_MODE)
00042 #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
00043 #elif defined(_WIN32)
00044 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
00045 #elif defined(__linux__)
00046 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
00047 #elif defined(ABSL_HAVE_SEMAPHORE_H)
00048 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
00049 #else
00050 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_CONDVAR
00051 #endif
00052
00053 namespace absl {
00054 namespace synchronization_internal {
00055
00056
00057 class Waiter {
00058 public:
00059
00060
00061 Waiter() = delete;
00062 Waiter(const Waiter&) = delete;
00063 Waiter& operator=(const Waiter&) = delete;
00064
00065
00066 void Init();
00067
00068
00069
00070
00071 bool Wait(KernelTimeout t);
00072
00073
00074 void Post();
00075
00076
00077
00078
00079 void Poke();
00080
00081
00082 static Waiter* GetWaiter(base_internal::ThreadIdentity* identity) {
00083 static_assert(
00084 sizeof(Waiter) <= sizeof(base_internal::ThreadIdentity::WaiterState),
00085 "Insufficient space for Waiter");
00086 return reinterpret_cast<Waiter*>(identity->waiter_state.data);
00087 }
00088
00089
00090 #ifndef THREAD_SANITIZER
00091 static const int kIdlePeriods = 60;
00092 #else
00093
00094
00095
00096 static const int kIdlePeriods = 1;
00097 #endif
00098
00099 private:
00100 #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
00101
00102
00103 std::atomic<int32_t> futex_;
00104 static_assert(sizeof(int32_t) == sizeof(futex_), "Wrong size for futex");
00105
00106 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR
00107 pthread_mutex_t mu_;
00108 pthread_cond_t cv_;
00109 std::atomic<int> waiter_count_;
00110 std::atomic<int> wakeup_count_;
00111
00112 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
00113 sem_t sem_;
00114
00115
00116
00117 std::atomic<int> wakeups_;
00118
00119 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
00120
00121
00122
00123
00124
00125
00126
00127 using SRWLockStorage =
00128 typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
00129 using ConditionVariableStorage =
00130 typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
00131
00132
00133
00134 class WinHelper;
00135
00136 SRWLockStorage mu_storage_;
00137 ConditionVariableStorage cv_storage_;
00138 std::atomic<int> waiter_count_;
00139 std::atomic<int> wakeup_count_;
00140
00141 #else
00142 #error Unknown ABSL_WAITER_MODE
00143 #endif
00144 };
00145
00146 }
00147 }
00148
00149 #endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_