Boost C++ Libraries: Ticket #7800: this_thread::sleep_for for pthread environment with BOOST_THREAD_USES_CHRONO may wait repeatedly https://svn.boost.org/trac10/ticket/7800 <p> In 1.52 implementation for pthread environment, with BOOST_THREAD_USES_CHRONO, </p> <ul><li>this_thread::sleep_for(boost::chrono::seconds(n)) calls: </li><li>template &lt;class Rep, class Period&gt; void sleep_for(const chrono::duration&lt;Rep, Period&gt;&amp; d) in boost/thread/v2/thread.hpp, which calls: </li><li>void sleep_for(const chrono::nanoseconds&amp; ns) in boost/thread/pthread/thread_data.hpp, which calls: <div class="wiki-code"><div class="code"><pre> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">Rep</span><span class="p">,</span> <span class="k">class</span> <span class="nc">Period</span><span class="o">&gt;</span> <span class="n">cv_status</span> <span class="n">wait_for</span><span class="p">(</span> <span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">mutex</span><span class="o">&gt;&amp;</span> <span class="n">lock</span><span class="p">,</span> <span class="k">const</span> <span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="n">Rep</span><span class="p">,</span> <span class="n">Period</span><span class="o">&gt;&amp;</span> <span class="n">d</span><span class="p">)</span> <span class="p">{</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">chrono</span><span class="p">;</span> <span class="n">system_clock</span><span class="o">::</span><span class="n">time_point</span> <span class="n">s_now</span> <span class="o">=</span> <span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span> <span class="n">steady_clock</span><span class="o">::</span><span class="n">time_point</span> <span class="n">c_now</span> <span class="o">=</span> <span class="n">steady_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span> <span class="n">wait_until</span><span class="p">(</span><span class="n">lock</span><span class="p">,</span> <span class="n">s_now</span> <span class="o">+</span> <span class="n">ceil</span><span class="o">&lt;</span><span class="n">nanoseconds</span><span class="o">&gt;</span><span class="p">(</span><span class="n">d</span><span class="p">));</span> <span class="k">return</span> <span class="n">steady_clock</span><span class="o">::</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">c_now</span> <span class="o">&lt;</span> <span class="n">d</span> <span class="o">?</span> <span class="n">cv_status</span><span class="o">::</span><span class="nl">no_timeout</span> <span class="p">:</span> <span class="n">cv_status</span><span class="o">::</span><span class="n">timeout</span><span class="p">;</span> <span class="p">}</span> </pre></div></div></li></ul><p> 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: </p> <div class="wiki-code"><div class="code"><pre> <span class="k">while</span><span class="p">(</span><span class="n">cv_status</span><span class="o">::</span><span class="n">no_timeout</span><span class="o">==</span><span class="n">thread_info</span><span class="o">-&gt;</span><span class="n">sleep_condition</span><span class="p">.</span><span class="n">wait_for</span><span class="p">(</span><span class="n">lk</span><span class="p">,</span><span class="n">ns</span><span class="p">))</span> <span class="p">{}</span> </pre></div></div><p> <em>ns</em> is wait period and not touched in this statement. So, it tries to wait the same period again. </p> <p> This behavior can be observable in FreeBSD 8.3-STABLE and Cygwin for Boost 1.52. </p> <p> In trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/82046" title="Add static asserts on ExponentType requirements. Document requirements ...">r82046</a>, call graph and implementation have been changed. If BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined, </p> <ul><li>this_thread::sleep_for(boost::chrono::seconds(n)) calls: </li><li>template &lt;class Rep, class Period&gt; void sleep_for(const chrono::duration&lt;Rep, Period&gt;&amp; d) in boost/thread/v2/thread.hpp, which calls: </li><li>void sleep_for(const chrono::nanoseconds&amp; ns) in boost/thread/pthread/thread_data.hpp, which calls: </li><li>void sleep_for(const timespec&amp; ts) in libs/thread/src/pthread/thread.cpp, which calls: </li><li>bool do_wait_for(unique_lock&lt;mutex&gt;&amp; lock, struct timespec const &amp;timeout) in boost/thread/pthread/condition_variable_fwd.hpp, which calls: </li><li>bool do_wait_until(unique_lock&lt;mutex&gt;&amp; m, struct timespec const &amp;timeout) in boost/thread/pthread/condition_variable.hpp, which calls </li><li>pthread_cond_timedwait. </li></ul><p> If pthread_cond_timedwait returns ETIMEDOUT, the following loop in void sleep_for(const timespec&amp; ts) exits. So, there is no problem. </p> <div class="wiki-code"><div class="code"><pre> <span class="k">while</span><span class="p">(</span> <span class="n">thread_info</span><span class="o">-&gt;</span><span class="n">sleep_condition</span><span class="p">.</span><span class="n">do_wait_for</span><span class="p">(</span><span class="n">lk</span><span class="p">,</span><span class="n">ts</span><span class="p">))</span> <span class="p">{}</span> </pre></div></div><p> 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, </p> <ul><li>this_thread::sleep_for(boost::chrono::seconds(n)) calls: </li></ul><div class="wiki-code"><div class="code"><pre> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">Rep</span><span class="p">,</span> <span class="k">class</span> <span class="nc">Period</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">sleep_for</span><span class="p">(</span><span class="k">const</span> <span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="n">Rep</span><span class="p">,</span> <span class="n">Period</span><span class="o">&gt;&amp;</span> <span class="n">d</span><span class="p">)</span> <span class="p">{</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">chrono</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">d</span> <span class="o">&gt;</span> <span class="n">duration</span><span class="o">&lt;</span><span class="n">Rep</span><span class="p">,</span> <span class="n">Period</span><span class="o">&gt;::</span><span class="n">zero</span><span class="p">())</span> <span class="p">{</span> <span class="n">steady_clock</span><span class="o">::</span><span class="n">time_point</span> <span class="n">c_now</span> <span class="o">=</span> <span class="n">steady_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span> <span class="k">do</span> <span class="p">{</span> <span class="n">sleep_until</span><span class="p">(</span><span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">()</span> <span class="o">+</span> <span class="n">ceil</span><span class="o">&lt;</span><span class="n">nanoseconds</span><span class="o">&gt;</span><span class="p">(</span><span class="n">d</span><span class="p">));</span> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">steady_clock</span><span class="o">::</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">c_now</span> <span class="o">&lt;</span> <span class="n">d</span> <span class="p">);</span> <span class="p">}</span> <span class="p">}</span> </pre></div></div><p> in boost/thread/v2/thread.hpp. The similar analysis for 1.52 can be applied on the above function. It may wait <em>d</em> period again. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7800 Trac 1.4.3 viboes Mon, 17 Dec 2012 17:26:41 GMT owner, status, version changed https://svn.boost.org/trac10/ticket/7800#comment:1 https://svn.boost.org/trac10/ticket/7800#comment:1 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Anthony Williams</span> to <span class="trac-author">viboes</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> <li><strong>version</strong> <span class="trac-field-old">Boost Development Trunk</span> → <span class="trac-field-new">Boost 1.52.0</span> </li> </ul> <p> I guess this is a duplicate of <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7665" title="#7665: Bugs: this_thread::sleep_for no longer uses steady_clock in thread (closed: fixed)">#7665</a>: "this_thread::sleep_for no longer uses steady_clock in thread". </p> <p> Please, could you check it and confirm? </p> Ticket viboes Fri, 21 Dec 2012 22:19:27 GMT status changed; resolution set; milestone deleted https://svn.boost.org/trac10/ticket/7800#comment:2 https://svn.boost.org/trac10/ticket/7800#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">duplicate</span> </li> <li><strong>milestone</strong> <span class="trac-field-deleted">To Be Determined</span> </li> </ul> Ticket