I have an application that needs to do work within certain windows (in this case, the windows are all 30 seconds apart). When the time is not within a window, the time until the middle of the next window is calculated, and the thread sleeps for that amount of time (in milliseconds, using boost::this_thread::sleep_for
).
Using Boost 1.55, I was able to hit the windows within my tolerance (+/-100ms) with extreme reliability. Upon migration to Boost 1.58, I am never able to hit these windows. Replacing the boost::this_thread::sleep_for
with std::this_thread::sleep_for
fixes the issue; however, I need the interruptible feature of boost::thread
and the interruption point that boost::this_thread::sleep_for
provides.
Here is some sample code illustrating the issue:
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <chrono>
#include <iostream>
#include <thread>
void boostThreadFunction ()
{
std::cout << "Starting Boost thread" << std::endl;
for (int i = 0; i < 10; ++i)
{
auto sleep_time = boost::chrono::milliseconds {29000 + 100 * i};
auto mark = std::chrono::steady_clock::now ();
boost::this_thread::sleep_for (sleep_time);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now () - mark);
std::cout << "Boost thread:" << std::endl;
std::cout << "\tSupposed to sleep for:\t" << sleep_time.count ()
<< " ms" << std::endl;
std::cout << "\tActually slept for:\t" << duration.count ()
<< " ms" << std::endl << std::endl;
}
}
void stdThreadFunction ()
{
std::cout << "Starting Std thread" << std::endl;
for (int i = 0; i < 10; ++i)
{
auto sleep_time = std::chrono::milliseconds {29000 + 100 * i};
auto mark = std::chrono::steady_clock::now ();
std::this_thread::sleep_for (sleep_time);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now () - mark);
std::cout << "Std thread:" << std::endl;
std::cout << "\tSupposed to sleep for:\t" << sleep_time.count ()
<< " ms" << std::endl;
std::cout << "\tActually slept for:\t" << duration.count ()
<< " ms" << std::endl << std::endl;
}
}
int main ()
{
boost::thread boost_thread (&boostThreadFunction);
std::this_thread::sleep_for (std::chrono::seconds (10));
std::thread std_thread (&stdThreadFunction);
boost_thread.join ();
std_thread.join ();
return 0;
}
Here is the output when referencing Boost 1.58 as an include directory and running on my workstation (Windows 7 64-bit):
Starting Boost thread
Starting Std thread
Boost thread:
Supposed to sleep for: 29000 ms
Actually slept for: 29690 ms
Std thread:
Supposed to sleep for: 29000 ms
Actually slept for: 29009 ms
Boost thread:
Supposed to sleep for: 29100 ms
Actually slept for: 29999 ms
Std thread:
Supposed to sleep for: 29100 ms
Actually slept for: 29111 ms
Boost thread:
Supposed to sleep for: 29200 ms
Actually slept for: 29990 ms
Std thread:
Supposed to sleep for: 29200 ms
Actually slept for: 29172 ms
Boost thread:
Supposed to sleep for: 29300 ms
Actually slept for: 30005 ms
Std thread:
Supposed to sleep for: 29300 ms
Actually slept for: 29339 ms
Boost thread:
Supposed to sleep for: 29400 ms
Actually slept for: 30003 ms
Std thread:
Supposed to sleep for: 29400 ms
Actually slept for: 29405 ms
Boost thread:
Supposed to sleep for: 29500 ms
Actually slept for: 29999 ms
Std thread:
Supposed to sleep for: 29500 ms
Actually slept for: 29472 ms
Boost thread:
Supposed to sleep for: 29600 ms
Actually slept for: 29999 ms
Std thread:
Supposed to sleep for: 29600 ms
Actually slept for: 29645 ms
Boost thread:
Supposed to sleep for: 29700 ms
Actually slept for: 29998 ms
Std thread:
Supposed to sleep for: 29700 ms
Actually slept for: 29706 ms
Boost thread:
Supposed to sleep for: 29800 ms
Actually slept for: 29998 ms
Std thread:
Supposed to sleep for: 29800 ms
Actually slept for: 29807 ms
Boost thread:
Supposed to sleep for: 29900 ms
Actually slept for: 30014 ms
Std thread:
Supposed to sleep for: 29900 ms
Actually slept for: 29915 ms
I would expect the std::thread
and the boost::thread
to sleep for the same amount of time; however, the boost::thread
seems to want to sleep for ~30 seconds when asked to sleep for 29.1 - 29.9 seconds. Am I misusing the boost::thread
interface, or is this a bug that was introduced since 1.55?