I am looking for a way to execute some code every X seconds but if an event occurs during the X seconds, break immediately.
Originally I had a while loop with a sleep statement at the end. However this was problematic because if the code was sleeping, I couldnt stop the code immediately and had to wait until the sleep had finished.
Is there any simple way I can execute then sleep, but interrupt this sleep on an event?
EDIT: Opted for a condition variable with notify_all().
You seem to have already found out an answer but conditional wait on mutex is the best solution here. You can essentially lock the mutex and throw it in a wait condition object along with some timeout. Some other thread can then signal/notify your thread using the same (shared) wait condition object. If nobody notifies/signals the mutex within specified timeout, the wait will simply come out of sleep.
The advantage of this interruptible sleep is that it's not a busy waiting.
I don't think you can interrupt sleep but you could have your code sleeping in shorter intervals and check for a signal regularly.
#include <thread>
#include <chrono>
int main()
{
using namespace std::chrono;
unsigned Y = 100;
unsigned X = 1;
bool signaled = false;
while (!signaled)
{
// Do Stuff every X seconds
high_resolution_clock::time_point const p = high_resolution_clock::now();
while (duration_cast<milliseconds>(high_resolution_clock::now() - p).count() <
duration_cast<milliseconds>(std::chrono::seconds(X)).count())
{
// Code to check for a signal every Y milliseconds
if (signaled)
{
break;
}
std::this_thread::sleep_for(milliseconds(Y));
}
}
return 0;
}
Note: System depedant clock resolutions; Possible trade-off with respect to CPU load when adjusting signal check frequency (depending on the demand of the signal check code);
Related
I prefer using condition_variable::wait_for as a timer over chrono based timer since I can override the wait condition by specifying a predicate. So I wrote a test program to check what if the delay duration changes once the wait process has already started. The condition_variable::wait_for seems to ignore the change and instead comes out of the wait process entirely. Why is this? Can I ever change it in the middle of a wait process?
enum STATE {START,STOP,NONE};
STATE state ;
condition_variable cv;
mutex mu;
chrono::milliseconds delay;
void cv_wait_thread()
{
{
unique_lock<mutex> lock(mu);
cv.wait(lock, [](){ return state == START; });
}
chrono::time_point<chrono::high_resolution_clock> start_time = chrono::high_resolution_clock::now();
{
unique_lock<mutex> lock(mu);
cv.wait_for(lock, delay);
}
auto diff = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time);
cout << "Conditional_wait: "<< diff.count() << " milliseconds" << endl;
}
void main()
{
thread thread1([](){ cv_wait_thread(); });
state = NONE;
this_thread::sleep_for(chrono::seconds(1));
delay = chrono::milliseconds(3000);
state = START;
cv.notify_all(); // ask thread to sleep for 3 sec
this_thread::sleep_for(chrono::milliseconds(2000)); // let cv_wait thread start the wait process for at least 2 sec already
delay = chrono::milliseconds(5000); // ask thread to correct and sleep for 5 sec instead
cv.notify_all();
thread1.join(); // thread prints 2000 milli
}
As you can see in the specification of the wait_for() method, the delay interval is specified as a const parameter:
template< class Rep, class Period >
std::cv_status wait_for( std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& rel_time);
Furthermore, there's nothing in the specification of wait_for() that indicates that any changes to the parameter will be observable by the thread that's executing the wait_for().
In fact, the only sequencing here comes as an indirect result of releasing and re-acquiring the underlying mutex. Note, however, that this will not occur until after the specified timeout expires. As such, any changes made to the delay parameter by another thread will not be sequenced until that time, and will not be observable by the thread that's executing the wait_for() call.
Note, that if the thread in question was doing something other than locking the mutex and executing wait_for(), unless the main execution thread explicitly does something that sequences its change to delay with respect to the other thread, the other thread is not guaranteed to observe the new value of delay ever.
This is my code using QueryPeformanceCounter as timer.
//timer.h
class timer {
private:
...
public:
...
double get(); //returns elapsed time in seconds
void start();
};
//a.cpp
void loop() {
timer t;
double tick;
double diff; //surplus seconds
t.start();
while( running ) {
tick = t.get();
if( tick >= 1.0 - diff ) {
t.start();
//things that should be run exactly every second
...
}
Sleep( 880 );
}
}
Without Sleep this loop would go on indefinitely calling t.get() every time which causes high CPU usage. For that reason, I make it sleep for about 880 milliseconds so that it wouldn't call t.get() while not necessary.
As I said above, I'm currently using Sleep to do the trick, but what I'm worried about is the accuracy of Sleep. I've read somewhere that the actual milliseconds the program pauses may vary - 20 to 50 ms - the reason I set the parameter to 880. I want to reduce the CPU usage as much as possible; I want to, if possible, pause more than 990 milliseconds EDIT: and yet less than 1000 milliseconds between every loop. What would be the best way to go?
I don't get why you are calling t.start() twice (it resets the clock?), but I would like to propose a kind of solution for the Sleep inaccuracy. Let's take a look at the content of while( running ) loop and follow the algorithm:
double future, remaining, sleep_precision = 0.05;
while (running) {
future = t.get() + 1.0;
things_that_should_be_run_exactly_every_second();
// the loop in case of spurious wakeup
for (;;) {
remaining = future - t.get();
if (remaining < sleep_precision) break;
Sleep(remaining);
}
// next, do the spin-lock for at most sleep_precision
while (t.get() < future);
}
The value of sleep_precision should be set empirically - OSes I know can't give you that.
Next, there are some alternatives of the sleeping mechanism that may better suit your needs - Is there an alternative for sleep() in C?
If you want to pause more than 990 milliseconds, write a sleep for 991 milliseconds. Your thread is guaranteed to be asleep for at least that long. It won't be less, but it could be multiples of 20-50ms more (depending on the resolution of your OS's time slicing, and on the the cost of context switching).
However, this will not give you something running "exactly every second". There is just no way to achieve that on a time-shared operating system. You'll have to program closer to the metal, or rely on an interrupt from a PPS source and just pray your OS lets you run your entire loop iteration in one shot. Or, I suppose, write something to run in kernel modeā¦?
As it turns out, condition_variable::wait_for should really be called condition_variable::wait_for_or_possibly_indefinitely_longer_than, because it needs to reacquire the lock before really timing out and returning.
See this program for a demonstration.
Is there a way to express, "Look, I really only have two seconds. If myPredicate() is still false at that time and/or the lock is still locked, I don't care, just carry on regardless and give me a way to detect that."
Something like:
bool myPredicate();
auto sec = std::chrono::seconds(1);
bool pred;
std::condition_variable::cv_status timedOut;
std::tie( pred, timedOut ) =
cv.really_wait_for_no_longer_than( lck, 2*sec, myPredicate );
if( lck.owns_lock() ) {
// Can use mutexed resource.
// ...
lck.unlock();
} else {
// Cannot use mutexed resource. Deal with it.
};
I think that you misuse the condition_variable's lock. It's for protecting condition only, not for protecting a time-consuming work.
Your example can be fixed easily by splitting the mutex into two - one is for critical section, another is for protecting modifications of ready condition. Here is the modified fragment:
typedef std::unique_lock<std::mutex> lock_type;
auto sec = std::chrono::seconds(1);
std::mutex mtx_work;
std::mutex mtx_ready;
std::condition_variable cv;
bool ready = false;
void task1() {
log("Starting task 1. Waiting on cv for 2 secs.");
lock_type lck(mtx_ready);
bool done = cv.wait_for(lck, 2*sec, []{log("Checking condition..."); return ready;});
std::stringstream ss;
ss << "Task 1 finished, done==" << (done?"true":"false") << ", " << (lck.owns_lock()?"lock owned":"lock not owned");
log(ss.str());
}
void task2() {
// Allow task1 to go first
std::this_thread::sleep_for(1*sec);
log("Starting task 2. Locking and sleeping 2 secs.");
lock_type lck1(mtx_work);
std::this_thread::sleep_for(2*sec);
lock_type lck2(mtx_ready);
ready = true; // This happens around 3s into the program
log("OK, task 2 unlocking...");
lck2.unlock();
cv.notify_one();
}
It's output:
#2 ms: Starting task 1. Waiting on cv for 2 secs.
#2 ms: Checking condition...
#1002 ms: Starting task 2. Locking and sleeping 2 secs.
#2002 ms: Checking condition...
#2002 ms: Task 1 finished, done==false, lock owned
#3002 ms: OK, task 2 unlocking...
Actually, the condition_variable::wait_for does exactly what you want. The problem with your example is that you locked a 2-second sleep along with the ready = true assignment, making it impossible for the condition variable to even evaluate the predicate before reaching the time limit.
Put that std::this_thread::sleep_for(2*sec); line outside the lock and see for yourself.
Is there a way to express, "Look, I really only have two seconds. If
myPredicate() is still false at that time and/or the lock is still
locked, I don't care, just carry on regardless ..."
Yes, there is a way, but unfortunately in case of wait_for it has to be manual. The wait_for waits indefinitely because of Spurious Wakeup. Imagine your loop like this:
while(!myPredicate())
cv.wait_for(lock, std::chrono::duration::seconds(2);
The spurious wakeup can happen anytime in an arbitrary platform. Imagine that in your case it happens within 200 ms. Due to this, without any external notification wait_for() will wakeup and check for myPredicate() in the loop condition.
As expected, the condition will be false, hence the loop will be true and again it will execute cv.wait_for(..), with fresh 2 seconds. This is how it will run infinitely.
Either you control that updation duration by yourself or use wait_until() which is ultimately called in wait_for().
I am working in a kind of "control block" that has to send a flag each 6 minutes. The thing is that I don't know if there is a simple way of doing this. I have had though in use clock_t inside a loop till it reaches the 6 minutes, and then call a method that sends the flag and re-initialize the clock_t variable.
I forgot to explain something, sleep is not an option because the block works like a flow, it has to send something the whole time. Actually the flag will change what is sending
Thanks in advance
You can just sleep the thread for 6 minutes and then send the flag:
for(;;)
{
sendFlag();
sleep(6*60);
}
Here are some options for the sleep method, including C++11's std::this_thread::sleep_for.
You could simply use a thread function that switches a flag on or off and sleep it for 6 minutes at a time. For example:
bool flag = false;
int main() {
while(true) {
if (flag == true) {
flag = false;
}
}
return(0);
}
void threadFunc() {
flag = true;
sleep(360); //360 seconds is 6 minutes
}
NOTE: You will need to use a mutex or semaphore because the code written now is not thread safe. How you use threads is also operating system dependent. Unless you use C++11 of course.
You don't need a whole thread just for this. Use a system OS periodic timer callback.
I'm in a worker thread and want to sleep for a specified period of time (usually a few hundreds milliseconds), but the sleep should be interruptible. Here is what I have come up with
void DummyScope::sleepForSamples() {
if(m_sampleSleep < 100) {
MySleeper::sleep(m_sampleSleep);
return;
}
// sleep in periods of 100 ms, to be responsible for shutdown requests
qint64 t = QDateTime::currentMSecsSinceEpoch();
qint64 end = t + m_sampleSleep;
while(t + 100 <= end) {
MySleeper::sleep(100);
t = QDateTime::currentMSecsSinceEpoch();
// TODO: check here whether we are interrupted
}
if(end > t) {
MySleeper::sleep(end - t);
}
}
However that looks a bit convoluted and I wonder whether there's a better way to do this. Is using a QWaitCondition with a timeout-wait a better solution?
'Is using a QWaitCondition with a timeout-wait a better solution?'
Yes!
The sleep() loop, apart from needlessly running every 100ms, has an average 'interrupt' latency of 50ms.
Definitely wait on a condition variable and let the accompanying condition tell you why you were interrupted.
If you don't have to use QT-threads, c++11 and boost let you add a predicate to wait_for/timed_wait, so spurious wakeups don't mess with your timeout.
Of course, it is even more convienent if you can go 1 step further and don't bother with a timeout (if the condition variable can handle all cases).
You can wait directly on the mutex with QMutex::tryLock(int timeout), if you lock and unlock it from another thread.