diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
commit | 9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /mozglue/misc/ConditionVariable_windows.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mozglue/misc/ConditionVariable_windows.cpp')
-rw-r--r-- | mozglue/misc/ConditionVariable_windows.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/mozglue/misc/ConditionVariable_windows.cpp b/mozglue/misc/ConditionVariable_windows.cpp new file mode 100644 index 0000000000..0c0151f1d3 --- /dev/null +++ b/mozglue/misc/ConditionVariable_windows.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Assertions.h" + +#include <float.h> +#include <intrin.h> +#include <stdlib.h> +#include <windows.h> + +#include "mozilla/PlatformConditionVariable.h" +#include "mozilla/PlatformMutex.h" +#include "MutexPlatformData_windows.h" + +// Some versions of the Windows SDK have a bug where some interlocked functions +// are not redefined as compiler intrinsics. Fix that for the interlocked +// functions that are used in this file. +#if defined(_MSC_VER) && !defined(InterlockedExchangeAdd) +# define InterlockedExchangeAdd(addend, value) \ + _InterlockedExchangeAdd((volatile long*)(addend), (long)(value)) +#endif + +#if defined(_MSC_VER) && !defined(InterlockedIncrement) +# define InterlockedIncrement(addend) \ + _InterlockedIncrement((volatile long*)(addend)) +#endif + +// Wrapper for native condition variable APIs. +struct mozilla::detail::ConditionVariableImpl::PlatformData { + CONDITION_VARIABLE cv_; +}; + +mozilla::detail::ConditionVariableImpl::ConditionVariableImpl() { + InitializeConditionVariable(&platformData()->cv_); +} + +void mozilla::detail::ConditionVariableImpl::notify_one() { + WakeConditionVariable(&platformData()->cv_); +} + +void mozilla::detail::ConditionVariableImpl::notify_all() { + WakeAllConditionVariable(&platformData()->cv_); +} + +void mozilla::detail::ConditionVariableImpl::wait(MutexImpl& lock) { + SRWLOCK* srwlock = &lock.platformData()->lock; + bool r = + SleepConditionVariableSRW(&platformData()->cv_, srwlock, INFINITE, 0); + MOZ_RELEASE_ASSERT(r); +} + +mozilla::CVStatus mozilla::detail::ConditionVariableImpl::wait_for( + MutexImpl& lock, const mozilla::TimeDuration& rel_time) { + if (rel_time == mozilla::TimeDuration::Forever()) { + wait(lock); + return CVStatus::NoTimeout; + } + + SRWLOCK* srwlock = &lock.platformData()->lock; + + // Note that DWORD is unsigned, so we have to be careful to clamp at 0. If + // rel_time is Forever, then ToMilliseconds is +inf, which evaluates as + // greater than UINT32_MAX, resulting in the correct INFINITE wait. We also + // don't want to round sub-millisecond waits to 0, as that wastes energy (see + // bug 1437167 comment 6), so we instead round submillisecond waits to 1ms. + double msecd = rel_time.ToMilliseconds(); + DWORD msec; + if (msecd < 0.0) { + msec = 0; + } else if (msecd > UINT32_MAX) { + msec = INFINITE; + } else { + msec = static_cast<DWORD>(msecd); + // Round submillisecond waits to 1ms. + if (msec == 0 && !rel_time.IsZero()) { + msec = 1; + } + } + + BOOL r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, msec, 0); + if (r) return CVStatus::NoTimeout; + MOZ_RELEASE_ASSERT(GetLastError() == ERROR_TIMEOUT); + return CVStatus::Timeout; +} + +mozilla::detail::ConditionVariableImpl::~ConditionVariableImpl() { + // Native condition variables don't require cleanup. +} + +inline mozilla::detail::ConditionVariableImpl::PlatformData* +mozilla::detail::ConditionVariableImpl::platformData() { + static_assert(sizeof platformData_ >= sizeof(PlatformData), + "platformData_ is too small"); + return reinterpret_cast<PlatformData*>(platformData_); +} |