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.
Related
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.
So I'm trying to call a function every n seconds. The below is a simple representation of what I'm trying to achieve. I wanted to know if the below method is the only way to achieve this. I would love if the "if" condition can be avoided.
#include <stdio.h>
#include <time.h>
void print_hello(int i) {
printf("hello\n");
printf("%d\n", i);
}
int main () {
time_t start_t, end_t;
double diff_t;
time(&start_t);
int i = 0;
while(1) {
time(&end_t);
// printf("here in main");
i = i + 1;
diff_t = difftime(end_t, start_t);
if(diff_t==5) {
// printf("Execution time = %f\n", diff_t);
print_hello(i);
time(&start_t);
}
}
return(0);
}
The usage of time in OPs program can be reduced to something like
// get tStart;
// set tEnd = tStart + x;
do {
// get t;
} while (t < tEnd);
This is what is called busy-wait.
It might be used to write code with most precise timing as well as in other special cases. The draw-back is that the waiting consumes ful CPU load. (You might be even able to hear this – by raising ventilation noise.)
In general, however, spinning is considered an anti-pattern and should be avoided, as processor time that could be used to execute a different task is instead wasted on useless activity.
Another option is to delegate the wake-up to the system, which reduces the load of process/thread to minimum while waiting:
#include <chrono>
#include <iostream>
#include <thread>
void print_hello(int i)
{
std::cout << "hello\n"
<< i << '\n';
}
int main ()
{
using namespace std::chrono_literals; // to support e.g. 5s for 5 sceconds
auto tStart = std::chrono::system_clock::now();
for (int i = 1; i <= 3; ++i) {
auto tEnd = tStart + 2s;
std::this_thread::sleep_until(tEnd);
print_hello(i);
tStart = tEnd;
}
}
Output:
hello
1
hello
2
hello
3
Live Demo on coliru
(I had to reduce number of iterations and the waiting times to prevent the TLE in online compiler.)
std::this_thread::sleep_until
Blocks the execution of the current thread until specified sleep_time has been reached.
The clock tied to sleep_time is used, which means that adjustments of the clock are taken into account. Thus, the duration of the block might, but might not, be less or more than sleep_time - Clock::now() at the time of the call, depending on the direction of the adjustment. The function also may block for longer than until after sleep_time has been reached due to scheduling or resource contention delays.
The last sentence mentions the draw-back of this solution: The OS may decide to wake-up the thread/process later than requested. That may happen e.g. is OS is under high load. In the “normal” case, the latency shouldn't be more than a few milli-seconds. So, the latency might be tolerable.
Please, note how tEnd and tStart are updated in loop. The current wake-up time is not considered to prevent accumulation of latencies.
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.
I've implemented code to call a service API every 10 seconds using a c++ client. Most of the times I've noticed it is around 10 seconds but occassionally I see an issue like below where it look longer. I'm using conditional variable on wait_until. What's wrong with my implementation? Any ideas?
Here's the timing output:
currentDateTime()=2015-12-21.15:13:21
currentDateTime()=2015-12-21.15:13:57
And the code:
void client::runHeartbeat() {
std::unique_lock<std::mutex> locker(lock);
for (;;) {
// check the current time
auto now = std::chrono::system_clock::now();
/* Set a condition on the conditional variable to wake up the this thread.
This thread is woken up on 2 conditions:
1. After a timeout of now + interval when we want to send the next heartbeat
2. When the client is destroyed.
*/
shutdownHeartbeat.wait_until(locker, now + std::chrono::milliseconds(sleepMillis));
// After waking up we want to check if a sign-out has occurred.
if (m_heartbeatRunning) {
std::cout << "currentDateTime()=" << currentDateTime() << std::endl;
SendHeartbeat();
}
else {
break;
}
}
}
You might want to consider using the high_resolution_clock for your needs. system_clock is not guaranteed a high resolution, so that may be a part of the problem.
Note that it's definition is implementation dependent so you might just get a typedef back onto system_clock on some compilers.
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...