diff --git a/asio/include/asio/detail/conditionally_enabled_mutex.hpp b/asio/include/asio/detail/conditionally_enabled_mutex.hpp index 27fc30ecbb..6d2bdaa2a5 100644 --- a/asio/include/asio/detail/conditionally_enabled_mutex.hpp +++ b/asio/include/asio/detail/conditionally_enabled_mutex.hpp @@ -70,6 +70,14 @@ class conditionally_enabled_mutex { if (mutex_.enabled_ && !locked_) { + for (int n = mutex_.spin_count_; n != 0; n -= (n > 0) ? 1 : 0) + { + if (mutex_.mutex_.try_lock()) + { + locked_ = true; + return; + } + } mutex_.mutex_.lock(); locked_ = true; } @@ -104,8 +112,9 @@ class conditionally_enabled_mutex }; // Constructor. - explicit conditionally_enabled_mutex(bool enabled) - : enabled_(enabled) + explicit conditionally_enabled_mutex(bool enabled, int spin_count = 0) + : spin_count_(spin_count), + enabled_(enabled) { } @@ -124,7 +133,12 @@ class conditionally_enabled_mutex void lock() { if (enabled_) + { + for (int n = spin_count_; n != 0; n -= (n > 0) ? 1 : 0) + if (mutex_.try_lock()) + return; mutex_.lock(); + } } // Unlock the mutex. @@ -138,6 +152,7 @@ class conditionally_enabled_mutex friend class scoped_lock; friend class conditionally_enabled_event; asio::detail::mutex mutex_; + const int spin_count_; const bool enabled_; }; diff --git a/asio/include/asio/detail/impl/scheduler.ipp b/asio/include/asio/detail/impl/scheduler.ipp index 45137a69a5..449c09ebf5 100644 --- a/asio/include/asio/detail/impl/scheduler.ipp +++ b/asio/include/asio/detail/impl/scheduler.ipp @@ -112,7 +112,8 @@ scheduler::scheduler(asio::execution_context& ctx, bool own_thread, get_task_func_type get_task) : asio::detail::execution_context_service_base(ctx), one_thread_(config(ctx).get("scheduler", "concurrency_hint", 0) == 1), - mutex_(config(ctx).get("scheduler", "locking", true)), + mutex_(config(ctx).get("scheduler", "locking", true), + config(ctx).get("scheduler", "locking_spin_count", 0)), task_(0), get_task_(get_task), task_interrupted_(true), diff --git a/asio/include/asio/detail/null_static_mutex.hpp b/asio/include/asio/detail/null_static_mutex.hpp index 15d649bb0d..5eb72e8a46 100644 --- a/asio/include/asio/detail/null_static_mutex.hpp +++ b/asio/include/asio/detail/null_static_mutex.hpp @@ -35,6 +35,12 @@ struct null_static_mutex { } + // Try to lock the mutex without blocking. + bool try_lock() + { + return true; + } + // Lock the mutex. void lock() { diff --git a/asio/include/asio/detail/posix_mutex.hpp b/asio/include/asio/detail/posix_mutex.hpp index 38ce2867ff..a60d9e3ee7 100644 --- a/asio/include/asio/detail/posix_mutex.hpp +++ b/asio/include/asio/detail/posix_mutex.hpp @@ -45,6 +45,12 @@ class posix_mutex ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY. } + // Try to lock the mutex. + bool try_lock() + { + return ::pthread_mutex_trylock(&mutex_) == 0; // Ignore EINVAL. + } + // Lock the mutex. void lock() { diff --git a/asio/include/asio/detail/std_mutex.hpp b/asio/include/asio/detail/std_mutex.hpp index 06839d69ca..e038456d26 100644 --- a/asio/include/asio/detail/std_mutex.hpp +++ b/asio/include/asio/detail/std_mutex.hpp @@ -43,6 +43,12 @@ class std_mutex { } + // Try to lock the mutex. + bool try_lock() + { + return mutex_.try_lock(); + } + // Lock the mutex. void lock() { diff --git a/asio/include/asio/detail/win_mutex.hpp b/asio/include/asio/detail/win_mutex.hpp index 77603ec975..5f4e717ed9 100644 --- a/asio/include/asio/detail/win_mutex.hpp +++ b/asio/include/asio/detail/win_mutex.hpp @@ -43,6 +43,12 @@ class win_mutex ::DeleteCriticalSection(&crit_section_); } + // Try to lock the mutex. + bool try_lock() + { + return ::TryEnterCriticalSection(&crit_section_) != 0; + } + // Lock the mutex. void lock() {