diff options
Diffstat (limited to 'absl')
-rw-r--r-- | absl/base/internal/thread_identity.h | 2 | ||||
-rw-r--r-- | absl/synchronization/BUILD.bazel | 2 | ||||
-rw-r--r-- | absl/synchronization/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/synchronization/internal/stdcpp_waiter.cc | 91 | ||||
-rw-r--r-- | absl/synchronization/internal/stdcpp_waiter.h | 56 | ||||
-rw-r--r-- | absl/synchronization/internal/waiter.h | 4 | ||||
-rw-r--r-- | absl/synchronization/internal/waiter_test.cc | 5 |
7 files changed, 161 insertions, 1 deletions
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index b99c9575..496ec214 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -147,7 +147,7 @@ struct ThreadIdentity { // Private: Reserved for absl::synchronization_internal::Waiter. struct WaiterState { - alignas(void*) char data[128]; + alignas(void*) char data[256]; } waiter_state; // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter(). diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index 40843b35..adf6ae2f 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -90,6 +90,7 @@ cc_library( "internal/per_thread_sem.cc", "internal/pthread_waiter.cc", "internal/sem_waiter.cc", + "internal/stdcpp_waiter.cc", "internal/waiter_base.cc", "internal/win32_waiter.cc", "mutex.cc", @@ -104,6 +105,7 @@ cc_library( "internal/per_thread_sem.h", "internal/pthread_waiter.h", "internal/sem_waiter.h", + "internal/stdcpp_waiter.h", "internal/waiter.h", "internal/waiter_base.h", "internal/win32_waiter.h", diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index d95e327f..9926fb72 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -75,6 +75,7 @@ absl_cc_library( "internal/per_thread_sem.h" "internal/pthread_waiter.h" "internal/sem_waiter.h" + "internal/stdcpp_waiter.h" "internal/waiter.h" "internal/waiter_base.h" "internal/win32_waiter.h" @@ -88,6 +89,7 @@ absl_cc_library( "internal/per_thread_sem.cc" "internal/pthread_waiter.cc" "internal/sem_waiter.cc" + "internal/stdcpp_waiter.cc" "internal/waiter_base.cc" "internal/win32_waiter.cc" "notification.cc" diff --git a/absl/synchronization/internal/stdcpp_waiter.cc b/absl/synchronization/internal/stdcpp_waiter.cc new file mode 100644 index 00000000..8b5d1df4 --- /dev/null +++ b/absl/synchronization/internal/stdcpp_waiter.cc @@ -0,0 +1,91 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/synchronization/internal/stdcpp_waiter.h" + +#ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER + +#include <chrono> // NOLINT(build/c++11) +#include <condition_variable> // NOLINT(build/c++11) +#include <mutex> // NOLINT(build/c++11) + +#include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" +#include "absl/base/internal/thread_identity.h" +#include "absl/base/optimization.h" +#include "absl/synchronization/internal/kernel_timeout.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace synchronization_internal { + +#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr char StdcppWaiter::kName[]; +#endif + +StdcppWaiter::StdcppWaiter() : waiter_count_(0), wakeup_count_(0) {} + +bool StdcppWaiter::Wait(KernelTimeout t) { + std::unique_lock<std::mutex> lock(mu_); + ++waiter_count_; + + // Loop until we find a wakeup to consume or timeout. + // Note that, since the thread ticker is just reset, we don't need to check + // whether the thread is idle on the very first pass of the loop. + bool first_pass = true; + while (wakeup_count_ == 0) { + if (!first_pass) MaybeBecomeIdle(); + // No wakeups available, time to wait. + if (!t.has_timeout()) { + cv_.wait(lock); + } else { + auto wait_result = t.is_relative_timeout() + ? cv_.wait_for(lock, t.ToChronoDuration()) + : cv_.wait_until(lock, t.ToChronoTimePoint()); + if (wait_result == std::cv_status::timeout) { + --waiter_count_; + return false; + } + } + first_pass = false; + } + + // Consume a wakeup and we're done. + --wakeup_count_; + --waiter_count_; + return true; +} + +void StdcppWaiter::Post() { + std::lock_guard<std::mutex> lock(mu_); + ++wakeup_count_; + InternalCondVarPoke(); +} + +void StdcppWaiter::Poke() { + std::lock_guard<std::mutex> lock(mu_); + InternalCondVarPoke(); +} + +void StdcppWaiter::InternalCondVarPoke() { + if (waiter_count_ != 0) { + cv_.notify_one(); + } +} + +} // namespace synchronization_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_INTERNAL_HAVE_STDCPP_WAITER diff --git a/absl/synchronization/internal/stdcpp_waiter.h b/absl/synchronization/internal/stdcpp_waiter.h new file mode 100644 index 00000000..e592a27b --- /dev/null +++ b/absl/synchronization/internal/stdcpp_waiter.h @@ -0,0 +1,56 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_ +#define ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_ + +#include <condition_variable> // NOLINT(build/c++11) +#include <mutex> // NOLINT(build/c++11) + +#include "absl/base/config.h" +#include "absl/synchronization/internal/kernel_timeout.h" +#include "absl/synchronization/internal/waiter_base.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace synchronization_internal { + +#define ABSL_INTERNAL_HAVE_STDCPP_WAITER 1 + +class StdcppWaiter : public WaiterCrtp<StdcppWaiter> { + public: + StdcppWaiter(); + + bool Wait(KernelTimeout t); + void Post(); + void Poke(); + + static constexpr char kName[] = "StdcppWaiter"; + + private: + // REQUIRES: mu_ must be held. + void InternalCondVarPoke(); + + std::mutex mu_; + std::condition_variable cv_; + int waiter_count_; + int wakeup_count_; // Unclaimed wakeups. +}; + +} // namespace synchronization_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_ diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h index 07bba10a..1a8b0b83 100644 --- a/absl/synchronization/internal/waiter.h +++ b/absl/synchronization/internal/waiter.h @@ -20,6 +20,7 @@ #include "absl/synchronization/internal/futex_waiter.h" #include "absl/synchronization/internal/pthread_waiter.h" #include "absl/synchronization/internal/sem_waiter.h" +#include "absl/synchronization/internal/stdcpp_waiter.h" #include "absl/synchronization/internal/win32_waiter.h" // May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index> @@ -27,6 +28,7 @@ #define ABSL_WAITER_MODE_SEM 1 #define ABSL_WAITER_MODE_CONDVAR 2 #define ABSL_WAITER_MODE_WIN32 3 +#define ABSL_WAITER_MODE_STDCPP 4 #if defined(ABSL_FORCE_WAITER_MODE) #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE @@ -54,6 +56,8 @@ using Waiter = SemWaiter; using Waiter = PthreadWaiter; #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32 using Waiter = Win32Waiter; +#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_STDCPP +using Waiter = StdcppWaiter; #endif } // namespace synchronization_internal diff --git a/absl/synchronization/internal/waiter_test.cc b/absl/synchronization/internal/waiter_test.cc index 92812965..5de11d26 100644 --- a/absl/synchronization/internal/waiter_test.cc +++ b/absl/synchronization/internal/waiter_test.cc @@ -22,6 +22,7 @@ #include "absl/synchronization/internal/kernel_timeout.h" #include "absl/synchronization/internal/pthread_waiter.h" #include "absl/synchronization/internal/sem_waiter.h" +#include "absl/synchronization/internal/stdcpp_waiter.h" #include "absl/synchronization/internal/thread_pool.h" #include "absl/synchronization/internal/win32_waiter.h" #include "absl/time/clock.h" @@ -147,5 +148,9 @@ INSTANTIATE_TYPED_TEST_SUITE_P(Sem, WaiterTest, INSTANTIATE_TYPED_TEST_SUITE_P(Win32, WaiterTest, absl::synchronization_internal::Win32Waiter); #endif +#ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER +INSTANTIATE_TYPED_TEST_SUITE_P(Stdcpp, WaiterTest, + absl::synchronization_internal::StdcppWaiter); +#endif } // namespace |