On an embedded platform I ran into the issue that when waiting on a condition until time_point<clock>::max(), the program enters a busy loop completely using a CPU.
The program I am running is:
#include <mutex>
#include <condition_variable>
#include <iostream>
int main() {
std::mutex mutex;
std::condition_variable condition;
using namespace std::chrono;
using clock = steady_clock;
for (;;) {
auto forever = time_point<clock>::max();
std::unique_lock<std::mutex> lock(mutex);
std::cout << "Now waiting" << std::endl;
condition.wait_until(lock, forever);
std::cout << "Now waking up" << std::endl;
}
return 0;
}
I was quite sure this is a bug, and running this on my host's compiler (g++ 4.7) the application behaved as I expected (blocking forever). When writing a bug report I wanted to attach an ideone sample demonstrating the issue, but ideone also runs into a busy loop:
http://ideone.com/XPy0Wn
Now I am unsure who is correct here. Is there a standard definition of how wait_until on a condition should behave when the second argument is time_point<clock>::max()?
You likely observe a (silly) conversion of steady clock to system clock time:
#include <chrono>
#include <iostream>
using namespace std::chrono;
time_t silly_steady_clock_to_time_t( steady_clock::time_point t )
{
return system_clock::to_time_t(system_clock::now()
+ (t - steady_clock::now()));
}
int main() {
auto system_time = system_clock::to_time_t(system_clock::now());
auto forever = time_point<steady_clock>::max();
auto forever_time = silly_steady_clock_to_time_t(forever);
std::cout << ctime(&forever_time) << '\n';
std::cout << ctime(&system_time) << '\n';
return 0;
}
Output:
Fri Jun 16 11:40:31 1724
Tue Sep 27 15:44:54 2016
Note: the steady forever_time is in the past.
A change of clock to using clock = system_clock; will fix the issue.
As mentioned in the comments, if you want to try to track it down, you should check the return type of the call to wait_until.
It can be either std::cv_status::timeout or std::cv_status::no_timeout.
By doing that, you'll be able to understand what's going on there.
As mentioned in the standard, the return type adheres to the following rules:
cv_status::timeout if the absolute timeout specified by abs_time expired, otherwise cv_status::no_timeout.
Moreover:
The function will unblock when signaled by a call to notify_one(), a call to notify_all(), expiration of the absolute timeout specified by abs_time, or spuriously.
Likely the last one is your case and it's unlikely a bug.
You should rather look for the reasons that give place to those spurious wakeups.
Related
The following behavior was seen under g++ 11.2.1 . The std::condition_variable wait_for method returns immediately if the timeout variable is too large. In particular in the program below, if num_years==1, then the program hangs waiting as expected (presumably for 1 year), but if the variable num_years==1000 then the program returns immediatly.
Why does this happen? Is this a bug in g++? And a related question, how do you make the cv.wait_for() wait indefinitely, instead of guessing a large timeout value?
// This is 'cv_wait.cc' compile with:
//
// g++ -o cv_wait -std=c++2a cv_wait.cc
//
// An example showing that wait_for() returns immediately with a timeout
// return value if the duration variable is "too large".
//
#include <iostream>
#include <condition_variable>
#include <chrono>
int main(int argc, char **argv)
{
std::condition_variable cv;
std::mutex cv_m;
// If num_years is "too large", e.g. 1000, then cv.wait_for()
// returns immediately with a timeout condition!
int num_years = 1; // If 1000 then cv.wait_for() returns immediately!
std::chrono::seconds timeout((uint64_t)3600 * 24 * 365 * num_years);
std::unique_lock<std::mutex> lock(cv_m);
if (cv.wait_for(lock, timeout, [] { return false; }))
std::cerr << "No timeout!\n";
else
std::cerr << "Timeout!\n";
}
This is an overflow bug under the hood of condition_variable::wait_for. Internally it is waiting using steady_clock which counts nanoseconds. This clock overflows at +/-292 years. So when 1000 years gets converted to nanoseconds, it is overflowing.
This looks like a standards bug as opposed to an implementation bug: http://eel.is/c++draft/thread.condition#condvar-24
The implementation should check for overflows of this type and in case found, just wait for the maximum time it is capable of waiting for.
Recently, I met a problem which is related with condition variable in C++. The code is shown below :
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
std::condition_variable cv;
std::mutex mutex;
int main(){
std::unique_lock<std::mutex> uniqueLock(mutex);
while (true)
{
if(cv.wait_for(uniqueLock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout)
{
std::cout << "has image" << std::endl;
}
else
{
std::cout<< "time out " << std::endl;
}
}
return 0;
}
The goal of this code is that : each time when condition variable is notified in another thread (cv.notify()), it show "has image " in the console, and if it can not be notified more than 1000 milliseconds, it shows "time out".
So the theoretical output of the above code is (because the condition variable is not notified) :
time out
time out
time out
time out
But when i execute this code in the Vs2015, I found that the output is strange:
has image
time out
has image
time out
time out
time out
has image
has image
time out
time out
time out
time out
time out
has image
has image
I would like to know why i have this output and how can i achieve my goal
Thanks !
I don't know what the cause of your error is (but there are some plausible explanations in the comments). However, one way to fix your issue is to use the other overload of wait_for, which includes a predicate.
It could look something like this (hasImage is just a bool here, replace it with something that makes sense for your needs - !imageStorage.empty() or similar):
while (true)
{
if (cv.wait_for(uniqueLock, std::chrono::milliseconds(1000), []() {return hasImage;}))
{
std::cout << "has image" << std::endl;
hasImage = false;
}
else
{
std::cout << "time out " << std::endl;
}
}
The pertinent point is that the predicate checks if there actually is a new image, and if there isn't then it should continue to wait.
One limitation with this method is that, if the predicate returns false (no image), then you don't know if the condition variable woke due to a spurious wakeup, a timeout, or if there actually was an image but another thread just took it away before this one woke up. But if that is something your design can handle, then this variation works very well.
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.
What is wrong with just calling .join()? If you insist you can check before you join:
#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.joinable())
thd.join();
}
Note that the behaviour is Undefined anyway if you fail to join a thread before program exit. Use
futures,
condition variables or
semaphores
to signal job completion if that's what you were trying to monitor.
I used gcc-4.8.1(configure: ./configure --prefix=/usr/local) to compile following code in Ubuntu 12.04, but when I ran it, it didn't work. it didn't stop to wait the mutex. It returned false, and outputed "Hello world!"
command: g++ -std=c++11 main.cpp -omain -pthread
When I used gcc-4.6(apt-get install g++) to compile it, it worked well. The program waited about ten seconds, and outputed "Hello world!"
#include <thread>
#include <iostream>
#include <chrono>
#include <mutex>
std::timed_mutex test_mutex;
void f()
{
test_mutex.try_lock_for(std::chrono::seconds(10));
std::cout << "hello world\n";
}
int main()
{
std::lock_guard<std::timed_mutex> l(test_mutex);
std::thread t(f);
t.join();
return 0;
}
If I am not mistaken, that is Bug 54562 -mutex and condition variable timers.
The reason for the bug is also mentioned:
This is because it uses the CLOCK_MONOTONIC clock (if available on the
platform) to calculate the absolute time when it needs to return,
which is incorrect as the POSIX pthread_mutex_timedlock() call uses
the CLOCK_REALTIME clock, and on my platform the monotonic clock is
way behind the real time clock.
However, this doesn't explain why you see the correct behavior on gcc-4.6 though. Perhaps _GLIBCXX_USE_CLOCK_MONOTONIC is not enabled?
A possible workaround:
const int WAIT_PRECISION_MS = 10; // Change it to whatever you like
int TIME_TO_WAIT_MS = 2000; // Change it to whatever you like
int ms_waited = 0;
bool got_lock = false;
while (ms_waited < TIME_TO_WAIT_MS) {
std::this_thread::sleep_for(
std::chrono::milliseconds(WAIT_PRECISION_MS));
ms_waited += WAIT_PRECISION_MS;
got_lock = YOUR_MUTEX.try_lock();
if (got_lock) {
break;
}
}
The WAIT_PRECISION_MS will tell the while loop how often to "wake up" and try getting the lock. But, it would also tell how accurate your deadline is going to be, unless your precision time is a factor of the deadline time.
For example:
deadline = 20, precision = 3: 3 is not a factor of 20 - the last iteration of the while loop will be when ms_waited is 18. It means that you are going to wait a total of 21ms and not 20ms.
deadline = 20, precision = 4: 4 is a factor of 20 - the last iteration of the while loop will be when ms_waited is 16. It means that you are going to wait exactly 20ms, as your deadline is defined.
I need to know how create a timer or measure out 500ms in C++ in a linux environment. I have tried using gettimeofday and using the time structure but cant get the correct precision for milliseconds. What I am trying to do is have an operation continue for a max of 500ms...after 500ms something else happens.
If you have access to C++11 then your best bet it to use std::chrono library
http://en.cppreference.com/w/cpp/chrono/duration
I aren't entirely sure what you want to do with it do you want to wait for exactly 500ms?
you can so this for that
std::this_thread::sleep_for(std::chrono::milliseconds(500));
you can do an operation until 500 milliseconds has elapsed by getting a time pointer and check to see whether timepoint - system_time::now() is greater than 500ms
//if you compiler supports it you can use auto
std::chrono::system_clock::time_point start=std::chrono::system_clock::now();
while(start-std::chrono::system_clock::now()
< std::chrono::milliseconds(500))
{
//do action
}
If you don't have C++11 this will also work with boost chrono library. The advantage of this approach is that it is portable unlike using linux time functions.
Your question isn't really clear about why you "can't get the correct precision" or what happens when you try to do that, but if you're having trouble with gettimeofday, consider using clock_gettime instead. man clock_gettime for details.
Since you are in Linux, you can use the system call usleep
int usleep(useconds_t usec);
Which will let your process sleep for some microseconds period.
#include <chrono>
#include <iostream>
#include <future>
#include <atomic>
void keep_busy(std::chrono::milliseconds this_long,std::atomic<bool> *canceled) {
auto start = std::chrono::high_resolution_clock::now();
while(std::chrono::high_resolution_clock::now() < start+this_long) {
std::cout << "work\n";
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if(canceled->load()) {
std::cout << "canceling op\n";
throw "operation canceled";
}
}
}
int main() {
std::atomic<bool> canceled(false);
auto future = std::async(std::launch::async,
keep_busy,std::chrono::milliseconds(600),&canceled);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
canceled.store(true);
try {
future.get();
std::cout << "operation succeded\n";
} catch( char const *e) {
std::cout << "operation failed due to: " << e << '\n';
}
}
I'm not entirely sure this is correct...