dennis.luxen created this revision.
This task is listed in TODO.txt. The implementation swaps mutex against a
spinlock based on atomic_flag. The spin lock itself is implemented as a nested
class in a protected context of the associated state.
https://reviews.llvm.org/D37677
Files:
include/future
src/future.cpp
Index: src/future.cpp
===================================================================
--- src/future.cpp
+++ src/future.cpp
@@ -91,7 +91,7 @@
void
__assoc_sub_state::set_value()
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (__has_value())
throw future_error(make_error_code(future_errc::promise_already_satisfied));
@@ -103,7 +103,7 @@
void
__assoc_sub_state::set_value_at_thread_exit()
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (__has_value())
throw future_error(make_error_code(future_errc::promise_already_satisfied));
@@ -115,7 +115,7 @@
void
__assoc_sub_state::set_exception(exception_ptr __p)
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (__has_value())
throw future_error(make_error_code(future_errc::promise_already_satisfied));
@@ -128,7 +128,7 @@
void
__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
#ifndef _LIBCPP_NO_EXCEPTIONS
if (__has_value())
throw future_error(make_error_code(future_errc::promise_already_satisfied));
@@ -140,29 +140,29 @@
void
__assoc_sub_state::__make_ready()
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
__state_ |= ready;
__cv_.notify_all();
}
void
__assoc_sub_state::copy()
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
__sub_wait(__lk);
if (__exception_ != nullptr)
rethrow_exception(__exception_);
}
void
__assoc_sub_state::wait()
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
__sub_wait(__lk);
}
void
-__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
+__assoc_sub_state::__sub_wait(unique_lock<__spin_lock>& __lk)
{
if (!__is_ready())
{
Index: include/future
===================================================================
--- include/future
+++ include/future
@@ -367,7 +367,8 @@
#include <memory>
#include <chrono>
#include <exception>
-#include <mutex>
+#include <atomic>
+#include <condition_variable>
#include <thread>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -533,12 +534,24 @@
{
protected:
exception_ptr __exception_;
- mutable mutex __mut_;
- mutable condition_variable __cv_;
+
+ mutable class __spin_lock
+ {
+ atomic_flag __locked_ = ATOMIC_FLAG_INIT ;
+ public:
+ void lock() {
+ while (__locked_.test_and_set(memory_order_acquire)) { ; }
+ }
+ void unlock() {
+ __locked_.clear(memory_order_release);
+ }
+ } __mut_;
+
+ mutable condition_variable_any __cv_;
unsigned __state_;
virtual void __on_zero_shared() _NOEXCEPT;
- void __sub_wait(unique_lock<mutex>& __lk);
+ void __sub_wait(unique_lock<__spin_lock>& __lk);
public:
enum
{
@@ -558,7 +571,7 @@
_LIBCPP_INLINE_VISIBILITY
void __set_future_attached()
{
- lock_guard<mutex> __lk(__mut_);
+ lock_guard<__spin_lock> __lk(__mut_);
__state_ |= __future_attached;
}
_LIBCPP_INLINE_VISIBILITY
@@ -596,7 +609,7 @@
future_status
__assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
{
- unique_lock<mutex> __lk(__mut_);
+ unique_lock<__spin_lock> __lk(__mut_);
if (__state_ & deferred)
return future_status::deferred;
while (!(__state_ & ready) && _Clock::now() < __abs_time)
@@ -663,7 +676,7 @@
__assoc_state<_Rp>::set_value(_Arg& __arg)
#endif
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
if (this->__has_value())
__throw_future_error(future_errc::promise_already_satisfied);
::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg));
@@ -680,7 +693,7 @@
__assoc_state<_Rp>::set_value_at_thread_exit(_Arg& __arg)
#endif
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
if (this->__has_value())
__throw_future_error(future_errc::promise_already_satisfied);
::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg));
@@ -692,7 +705,7 @@
_Rp
__assoc_state<_Rp>::move()
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
this->__sub_wait(__lk);
if (this->__exception_ != nullptr)
rethrow_exception(this->__exception_);
@@ -703,7 +716,7 @@
typename add_lvalue_reference<_Rp>::type
__assoc_state<_Rp>::copy()
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
this->__sub_wait(__lk);
if (this->__exception_ != nullptr)
rethrow_exception(this->__exception_);
@@ -739,7 +752,7 @@
void
__assoc_state<_Rp&>::set_value(_Rp& __arg)
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
if (this->__has_value())
__throw_future_error(future_errc::promise_already_satisfied);
__value_ = _VSTD::addressof(__arg);
@@ -751,7 +764,7 @@
void
__assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg)
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
if (this->__has_value())
__throw_future_error(future_errc::promise_already_satisfied);
__value_ = _VSTD::addressof(__arg);
@@ -763,7 +776,7 @@
_Rp&
__assoc_state<_Rp&>::copy()
{
- unique_lock<mutex> __lk(this->__mut_);
+ unique_lock<__spin_lock> __lk(this->__mut_);
this->__sub_wait(__lk);
if (this->__exception_ != nullptr)
rethrow_exception(this->__exception_);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits