diff --git a/include/future b/include/future index ad7af72b..1474ab0b 100644 --- a/include/future +++ b/include/future @@ -651,7 +651,6 @@ __assoc_state<_Rp>::set_value(_Arg& __arg) #endif ::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); this->__state_ |= base::__constructed | base::ready; - __lk.unlock(); __cv_.notify_all(); } @@ -672,7 +671,6 @@ __assoc_state<_Rp>::set_value_at_thread_exit(_Arg& __arg) ::new(&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); this->__state_ |= base::__constructed; __thread_local_data()->__make_ready_at_thread_exit(this); - __lk.unlock(); } template @@ -733,7 +731,6 @@ __assoc_state<_Rp&>::set_value(_Rp& __arg) #endif __value_ = _VSTD::addressof(__arg); this->__state_ |= base::__constructed | base::ready; - __lk.unlock(); __cv_.notify_all(); } @@ -749,7 +746,6 @@ __assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg) __value_ = _VSTD::addressof(__arg); this->__state_ |= base::__constructed; __thread_local_data()->__make_ready_at_thread_exit(this); - __lk.unlock(); } template diff --git a/src/future.cpp b/src/future.cpp index 0c5c2c44..3132b186 100644 --- a/src/future.cpp +++ b/src/future.cpp @@ -98,7 +98,6 @@ __assoc_sub_state::set_value() #endif __state_ |= __constructed | ready; __cv_.notify_all(); - __lk.unlock(); } void @@ -111,7 +110,6 @@ __assoc_sub_state::set_value_at_thread_exit() #endif __state_ |= __constructed; __thread_local_data()->__make_ready_at_thread_exit(this); - __lk.unlock(); } void @@ -124,7 +122,6 @@ __assoc_sub_state::set_exception(exception_ptr __p) #endif __exception_ = __p; __state_ |= ready; - __lk.unlock(); __cv_.notify_all(); } @@ -138,7 +135,6 @@ __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) #endif __exception_ = __p; __thread_local_data()->__make_ready_at_thread_exit(this); - __lk.unlock(); } void @@ -146,7 +142,6 @@ __assoc_sub_state::__make_ready() { unique_lock __lk(__mut_); __state_ |= ready; - __lk.unlock(); __cv_.notify_all(); } diff --git a/test/std/thread/futures/futures.async/async_race.pass.cpp b/test/std/thread/futures/futures.async/async_race.pass.cpp new file mode 100644 index 00000000..325a0271 --- /dev/null +++ b/test/std/thread/futures/futures.async/async_race.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads + +// + +// template +// future::type> +// async(F&& f, Args&&... args); + +// template +// future::type> +// async(launch policy, F&& f, Args&&... args); + +// This test is designed to cause and allow TSAN to detect the race condition +// reported in PR23293. (http://llvm.org/PR23293). + +#include +#include +#include +#include +#include + +int f_async() { + typedef std::chrono::milliseconds ms; + std::this_thread::sleep_for(ms(200)); + return 42; +} + +bool ran = false; + +int f_deferred() { + ran = true; + return 42; +} + +void test_each() { + { + std::future f = std::async(f_async); + int const result = f.get(); + assert(result == 42); + } + { + std::future f = std::async(std::launch::async, f_async); + int const result = f.get(); + assert(result == 42); + } + { + ran = false; + std::future f = std::async(std::launch::deferred, f_deferred); + assert(ran == false); + int const result = f.get(); + assert(ran == true); + assert(result == 42); + } +} + +int main() { + for (int i=0; i < 25; ++i) test_each(); +}