Export of internal Abseil changes.
-- 997d2a8d12d9395046b0bdfc2f206a0b2fe2f1f9 by Abseil Team <absl-team@google.com>: Typo fix: IsHashCallble -> IsHashCallable PiperOrigin-RevId: 245235915 -- 2baa4df2e3284df925bfd728bab7d7bd60ae002e by Eric Fiselier <ericwf@google.com>: Remove need for `Windows.h` header in `waiter.h` Ideally we never want to drag in `windows.h` because it's non-modular and hijacks global identifiers like `ERROR` and `OPAQUE`. This patch changes our waiter implementation to store char buffers for `SRWLOCK` and `CONDITION_VARIABLE` instead of the types directly. PiperOrigin-RevId: 245189428 -- 33cfacd70c0d148d7590472dbcce38c93f2f7a34 by Matthew Brown <matthewbr@google.com>: Internal change. PiperOrigin-RevId: 245092803 GitOrigin-RevId: 997d2a8d12d9395046b0bdfc2f206a0b2fe2f1f9 Change-Id: Icccd6cbe4b205096f6a71e114d135303ee4c1857
This commit is contained in:
parent
33841c5c96
commit
cd86d0d20a
4 changed files with 70 additions and 17 deletions
|
|
@ -40,6 +40,8 @@
|
|||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/thread_identity.h"
|
||||
|
|
@ -328,6 +330,43 @@ void Waiter::Poke() {
|
|||
|
||||
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
|
||||
|
||||
class Waiter::WinHelper {
|
||||
public:
|
||||
static SRWLOCK *GetLock(Waiter *w) {
|
||||
return reinterpret_cast<SRWLOCK *>(&w->mu_storage_);
|
||||
}
|
||||
|
||||
static CONDITION_VARIABLE *GetCond(Waiter *w) {
|
||||
return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_);
|
||||
}
|
||||
|
||||
static_assert(sizeof(SRWLOCK) == sizeof(Waiter::SRWLockStorage),
|
||||
"SRWLockStorage does not have the same size as SRWLOCK");
|
||||
static_assert(
|
||||
alignof(SRWLOCK) == alignof(Waiter::SRWLockStorage),
|
||||
"SRWLockStorage does not have the same alignment as SRWLOCK");
|
||||
|
||||
static_assert(sizeof(CONDITION_VARIABLE) ==
|
||||
sizeof(Waiter::ConditionVariableStorage),
|
||||
"ABSL_CONDITION_VARIABLE_STORAGE does not have the same size "
|
||||
"as CONDITION_VARIABLE");
|
||||
static_assert(alignof(CONDITION_VARIABLE) ==
|
||||
alignof(Waiter::ConditionVariableStorage),
|
||||
"ConditionVariableStorage does not have the same "
|
||||
"alignment as CONDITION_VARIABLE");
|
||||
|
||||
// The SRWLOCK and CONDITION_VARIABLE types must be trivially constuctible
|
||||
// and destructible because we never call their constructors or destructors.
|
||||
static_assert(std::is_trivially_constructible<SRWLOCK>::value,
|
||||
"The SRWLOCK type must be trivially constructible");
|
||||
static_assert(std::is_trivially_constructible<CONDITION_VARIABLE>::value,
|
||||
"The CONDITION_VARIABLE type must be trivially constructible");
|
||||
static_assert(std::is_trivially_destructible<SRWLOCK>::value,
|
||||
"The SRWLOCK type must be trivially destructible");
|
||||
static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value,
|
||||
"The CONDITION_VARIABLE type must be trivially destructible");
|
||||
};
|
||||
|
||||
class LockHolder {
|
||||
public:
|
||||
explicit LockHolder(SRWLOCK* mu) : mu_(mu) {
|
||||
|
|
@ -346,14 +385,19 @@ class LockHolder {
|
|||
};
|
||||
|
||||
void Waiter::Init() {
|
||||
InitializeSRWLock(&mu_);
|
||||
InitializeConditionVariable(&cv_);
|
||||
auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK;
|
||||
auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE;
|
||||
InitializeSRWLock(mu);
|
||||
InitializeConditionVariable(cv);
|
||||
waiter_count_.store(0, std::memory_order_relaxed);
|
||||
wakeup_count_.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
bool Waiter::Wait(KernelTimeout t) {
|
||||
LockHolder h(&mu_);
|
||||
SRWLOCK *mu = WinHelper::GetLock(this);
|
||||
CONDITION_VARIABLE *cv = WinHelper::GetCond(this);
|
||||
|
||||
LockHolder h(mu);
|
||||
waiter_count_.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
// Loop until we find a wakeup to consume or timeout.
|
||||
|
|
@ -371,8 +415,7 @@ bool Waiter::Wait(KernelTimeout t) {
|
|||
}
|
||||
|
||||
// No wakeups available, time to wait.
|
||||
if (!SleepConditionVariableSRW(
|
||||
&cv_, &mu_, t.InMillisecondsFromNow(), 0)) {
|
||||
if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) {
|
||||
// GetLastError() returns a Win32 DWORD, but we assign to
|
||||
// unsigned long to simplify the ABSL_RAW_LOG case below. The uniform
|
||||
// initialization guarantees this is not a narrowing conversion.
|
||||
|
|
@ -399,11 +442,11 @@ void Waiter::Poke() {
|
|||
return;
|
||||
}
|
||||
// Potentially a waker. Take the lock and check again.
|
||||
LockHolder h(&mu_);
|
||||
LockHolder h(WinHelper::GetLock(this));
|
||||
if (waiter_count_.load(std::memory_order_relaxed) == 0) {
|
||||
return;
|
||||
}
|
||||
WakeConditionVariable(&cv_);
|
||||
WakeConditionVariable(WinHelper::GetCond(this));
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue