Suppose that I have the following code:
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <iostream>
int main()
{
boost::thread thd([]{ std::cout << "str \n"; });
boost::this_thread::sleep_for(boost::chrono::seconds(3));
if (thd.try_join_for(boost::chrono::nanoseconds(1)))
{
std::cout << "Finished \n";
}
else
{
std::cout << "Running \n";
}
}
MSVC-12.0 and boost 1.55 gives me the different output each time when I start this program. For example,
str
Finished
str
Finished
str
Running
When I change boost::chrono::nanoseconds to boost::chrono::microseconds the output is looks as expected.
Why? What am I doing wrong? Is it a bug in boost library? Is there a ticket about in in boost bug tracker?
Thanks in advance.
Your program simply has a race, most probably due to the fact that 1 nanosecond is awfully short.
try_join_for
is implemented by calling try_join_until
, a function that will attempt joining until a certain timepoint has been reached:
// I stripped some unrelated template stuff from the code
// to make it more readable
bool try_join_for(const chrono::duration& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
bool try_join_until(const chrono::time_point& t)
{
system_clock::time_point s_now = system_clock::now();
bool joined= false;
do {
Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero())
return false; // in case the Clock::time_point t is already reached
// only here we attempt to join for the first time:
joined = try_join_until(s_now + d);
} while (! joined);
return true;
}
The problem is now that try_join_until
will check whether the requested time_point has been reached before attempting the join. As you can see, it needs to perform two other calls to clock::now()
and some computation to compare the obtained values to the deadline given by the user. This may or may not be completed before the clock jumps beyond your given 1 nanosecond deadline, resulting in the unpredictability of the output.
Be aware that in general timing dependent code like this is fragile. Even with timeouts in the order of milliseconds, if you get preempted at a bad point during execution and there is a high load on the CPU, you might miss a deadline in rare cases. So be sure to always chose your deadlines carefully and never make assumptions that a deadline will be big enough in all possible cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With