Opened 10 years ago
Closed 10 years ago
#7800 closed Bugs (duplicate)
this_thread::sleep_for for pthread environment with BOOST_THREAD_USES_CHRONO may wait repeatedly
Reported by: | Owned by: | viboes | |
---|---|---|---|
Milestone: | Component: | thread | |
Version: | Boost 1.52.0 | Severity: | Problem |
Keywords: | Cc: |
Description
In 1.52 implementation for pthread environment, with BOOST_THREAD_USES_CHRONO,
- this_thread::sleep_for(boost::chrono::seconds(n)) calls:
- template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) in boost/thread/v2/thread.hpp, which calls:
- void sleep_for(const chrono::nanoseconds& ns) in boost/thread/pthread/thread_data.hpp, which calls:
template <class Rep, class Period> cv_status wait_for( unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& d) { using namespace chrono; system_clock::time_point s_now = system_clock::now(); steady_clock::time_point c_now = steady_clock::now(); wait_until(lock, s_now + ceil<nanoseconds>(d)); return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; }
in boost/thread/pthread/condition_variable_fwd.hpp. This function can return cv_status::no_timeout, even if steady_cloke::now() - c_now is nearly equal to d. At the caller side, this function is used in loop condition:
while(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {}
ns is wait period and not touched in this statement. So, it tries to wait the same period again.
This behavior can be observable in FreeBSD 8.3-STABLE and Cygwin for Boost 1.52.
In trunk r82046, call graph and implementation have been changed. If BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined,
- this_thread::sleep_for(boost::chrono::seconds(n)) calls:
- template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) in boost/thread/v2/thread.hpp, which calls:
- void sleep_for(const chrono::nanoseconds& ns) in boost/thread/pthread/thread_data.hpp, which calls:
- void sleep_for(const timespec& ts) in libs/thread/src/pthread/thread.cpp, which calls:
- bool do_wait_for(unique_lock<mutex>& lock, struct timespec const &timeout) in boost/thread/pthread/condition_variable_fwd.hpp, which calls:
- bool do_wait_until(unique_lock<mutex>& m, struct timespec const &timeout) in boost/thread/pthread/condition_variable.hpp, which calls
- pthread_cond_timedwait.
If pthread_cond_timedwait returns ETIMEDOUT, the following loop in void sleep_for(const timespec& ts) exits. So, there is no problem.
while( thread_info->sleep_condition.do_wait_for(lk,ts)) {}
BOOST_HAS_NANOSLEEP is defined for both of FreeBSD and Cygwin. As a result, BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined. Therefore, problems for the environment has been resolved. However, if BOOST_THREAD_SLEEP_FOR_IS_STEADY is not defined,
- this_thread::sleep_for(boost::chrono::seconds(n)) calls:
template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) { using namespace chrono; if (d > duration<Rep, Period>::zero()) { steady_clock::time_point c_now = steady_clock::now(); do { sleep_until(system_clock::now() + ceil<nanoseconds>(d)); } while (steady_clock::now() - c_now < d ); } }
in boost/thread/v2/thread.hpp. The similar analysis for 1.52 can be applied on the above function. It may wait d period again.
Change History (2)
comment:1 by , 10 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Version: | Boost Development Trunk → Boost 1.52.0 |
comment:2 by , 10 years ago
Milestone: | To Be Determined |
---|---|
Resolution: | → duplicate |
Status: | assigned → closed |
I guess this is a duplicate of #7665: "this_thread::sleep_for no longer uses steady_clock in thread".
Please, could you check it and confirm?