From 9f883f6ad7377b88b79fa70cc5de68cbfb0213e4 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Thu, 3 Sep 2015 23:44:03 +0200 Subject: [PATCH 1/7] Add a possible implementation of a steady condition_variable. --- .../thread/pthread/condition_variable_fwd.hpp | 130 ++++++++++++++---- 1 file changed, 103 insertions(+), 27 deletions(-) diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 29efa876..598ff811 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -62,7 +62,23 @@ namespace boost boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); } #endif + +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + pthread_condattr_t attr; + int res2 = pthread_condattr_init(&attr); + if(res2) + { + #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + #endif + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_steady::condition_variable_steady() constructor failed in pthread_condattr_init")); + } + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + res2=pthread_cond_init(&cond,&attr); + pthread_condattr_destroy(&attr); +#else int const res2=pthread_cond_init(&cond,NULL); +#endif if(res2) { #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -94,7 +110,6 @@ namespace boost while(!pred()) wait(m); } - #if defined BOOST_THREAD_USES_DATETIME inline bool timed_wait( unique_lock& m, @@ -174,6 +189,8 @@ namespace boost } #endif +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + #ifdef BOOST_THREAD_USES_CHRONO template @@ -203,20 +220,6 @@ namespace boost return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } - template - bool - wait_until( - unique_lock& lock, - const chrono::time_point& t, - Predicate pred) - { - while (!pred()) - { - if (wait_until(lock, t) == cv_status::timeout) - return pred(); - } - return true; - } template @@ -234,6 +237,90 @@ namespace boost } + inline cv_status wait_until( + unique_lock& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#else +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template + cv_status + wait_for( + unique_lock& lock, + const chrono::duration& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + wait_until( + unique_lock& lock, + const chrono::time_point& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } template bool @@ -263,18 +350,7 @@ namespace boost void notify_one() BOOST_NOEXCEPT; void notify_all() BOOST_NOEXCEPT; -#ifdef BOOST_THREAD_USES_CHRONO - inline cv_status wait_until( - unique_lock& lk, - chrono::time_point tp) - { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); - if (do_wait_until(lk, ts)) return cv_status::no_timeout; - else return cv_status::timeout; - } -#endif + }; BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); From ac3f7eb0375aae4370d041d0b870c43ab8d5ddc5 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sat, 5 Sep 2015 16:17:36 +0200 Subject: [PATCH 2/7] comment sleep_for overload on nanoseconds on windows. --- include/boost/thread/win32/thread_data.hpp | 26 ++++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index 51f6273f..005f3ba5 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -280,12 +280,13 @@ namespace boost { interruptible_wait(abs_time); } -#ifdef BOOST_THREAD_USES_CHRONO - inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) - { - interruptible_wait(chrono::duration_cast(ns).count()); - } -#endif +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// interruptible_wait(chrono::duration_cast(ns).count()); +// } +//#endif namespace no_interruption_point { bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); @@ -306,12 +307,13 @@ namespace boost { non_interruptible_wait(abs_time); } -#ifdef BOOST_THREAD_USES_CHRONO - inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) - { - non_interruptible_wait(chrono::duration_cast(ns).count()); - } -#endif +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// non_interruptible_wait(chrono::duration_cast(ns).count()); +// } +//#endif } } From b30cde32d4d90f601acc136bd02a4cdcbf3ea602 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 8 Sep 2015 18:22:44 +0200 Subject: [PATCH 3/7] reverse the use of dattime and chrono when chrono is acceptable. --- include/boost/thread/win32/shared_mutex.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index fff97b73..27677abd 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -139,10 +139,11 @@ namespace boost void lock_shared() { -#if defined BOOST_THREAD_USES_DATETIME - BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); -#else +#ifdef BOOST_THREAD_USES_CHRONO BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now())); +#else + //#if defined BOOST_THREAD_USES_DATETIME + BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); #endif } @@ -389,10 +390,12 @@ namespace boost void lock() { -#if defined BOOST_THREAD_USES_DATETIME - BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); -#else + +#ifdef BOOST_THREAD_USES_CHRONO BOOST_VERIFY(try_lock_until(chrono::steady_clock::now())); +#else + //#if defined BOOST_THREAD_USES_DATETIME + BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); #endif } From c1ee2bfbd880826b3a893b131f53f1b3e34c6ae4 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 8 Sep 2015 18:25:20 +0200 Subject: [PATCH 4/7] fix issue with latch:wait when count is already 0. --- include/boost/thread/latch.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/thread/latch.hpp b/include/boost/thread/latch.hpp index 8fa9d963..dc921e68 100644 --- a/include/boost/thread/latch.hpp +++ b/include/boost/thread/latch.hpp @@ -72,6 +72,7 @@ namespace boost void wait() { boost::unique_lock lk(mutex_); + if (count_ == 0) return; std::size_t generation(generation_); cond_.wait(lk, detail::not_equal(generation, generation_)); } @@ -89,6 +90,7 @@ namespace boost cv_status wait_for(const chrono::duration& rel_time) { boost::unique_lock lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; std::size_t generation(generation_); return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_)) ? cv_status::no_timeout @@ -101,6 +103,7 @@ namespace boost cv_status wait_until(const chrono::time_point& abs_time) { boost::unique_lock lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; std::size_t generation(generation_); return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_)) ? cv_status::no_timeout From 242cf35c519fc886c13789f1f9a049571fde4cdc Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 8 Sep 2015 19:24:15 +0200 Subject: [PATCH 5/7] Try patch for oldticket #3926 - thread_specific_ptr + dlopen library causes a SIGSEGV --- src/pthread/once.cpp | 8 ++++---- src/pthread/thread.cpp | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pthread/once.cpp b/src/pthread/once.cpp index f61d74c8..7748d086 100644 --- a/src/pthread/once.cpp +++ b/src/pthread/once.cpp @@ -15,9 +15,9 @@ #include #include #include -#if defined BOOST_THREAD_PATCH +//#if defined BOOST_THREAD_PATCH #include // memcmp. -#endif +//#endif namespace boost { namespace thread_detail @@ -44,7 +44,7 @@ namespace boost } } -#if defined BOOST_THREAD_PATCH +//#if defined BOOST_THREAD_PATCH const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT; struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t { @@ -60,7 +60,7 @@ namespace boost } }; delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose; -#endif +//#endif } uintmax_atomic_t& get_once_per_thread_epoch() diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index aa29615d..c3fdff7b 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -35,6 +35,7 @@ #include #include #include +#include // memcmp. namespace boost { @@ -117,7 +118,7 @@ namespace boost } } -#if defined BOOST_THREAD_PATCH +//#if defined BOOST_THREAD_PATCH struct delete_current_thread_tls_key_on_dlclose_t { @@ -134,7 +135,7 @@ namespace boost } }; delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose; -#endif +//#endif void create_current_thread_tls_key() { From febe4a814db6439f18acb525164e7d1599c8b55c Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 8 Sep 2015 21:39:33 +0200 Subject: [PATCH 6/7] comment trace to see the error. --- example/tennis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/tennis.cpp b/example/tennis.cpp index 61d49b27..d560ecb9 100644 --- a/example/tennis.cpp +++ b/example/tennis.cpp @@ -50,7 +50,7 @@ void player(int active) while (state < GAME_OVER) { - std::cout << player_name(active) << ": Play." << std::endl; + //std::cout << player_name(active) << ": Play." << std::endl; state = other; cond.notify_all(); do From 2e17e028b1a729e91fe87511dda74ddd063abec4 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 8 Sep 2015 21:55:48 +0200 Subject: [PATCH 7/7] use serial_executor instead of serial_executor_cont. --- test/test_11611.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_11611.cpp b/test/test_11611.cpp index 9a0ffd41..744c52ef 100644 --- a/test/test_11611.cpp +++ b/test/test_11611.cpp @@ -13,6 +13,7 @@ #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION #include #include +#include #include using namespace std; @@ -28,7 +29,8 @@ int main() }); { - boost::serial_executor_cont serial(ex); + //boost::serial_executor_cont serial(ex); + boost::serial_executor serial(ex); for (size_t i = 0; i < 100000; i++) serial.submit([i] {