Subject: [Boost-bugs] [Boost C++ Libraries] #7800: this_thread::sleep_for for pthread environment with BOOST_THREAD_USES_CHRONO may wait repeatedly
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-12-17 17:01:56
#7800: this_thread::sleep_for for pthread environment with
BOOST_THREAD_USES_CHRONO may wait repeatedly
-------------------------------------+--------------------------------------
Reporter: atara-y@⦠| Owner: anthonyw
Type: Bugs | Status: new
Milestone: To Be Determined | Component: thread
Version: Boost Development Trunk | Severity: Problem
Keywords: |
-------------------------------------+--------------------------------------
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:
{{{
#!cpp
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:
{{{
#!cpp
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.
{{{
#!cpp
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:
{{{
#!cpp
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.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/7800> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:11 UTC