I need to periodically do a particular task and am currently using nanosleep.
The task needs to be run every second or every 10 seconds.
Is there a better way to do this than:
while(true)
{
doTask();
sleep();
}
Walter
One of the options could be to create a thread that will do the task with specified timeout.
You can use a thread library to create a thread which handle run the doTask(). Your main thread just keeps sleeping and runs every 1 second or 10 seconds.
This can be done with a QTimer and a QRunnable.
http://doc.qt.nokia.com/latest/qtimer.html
According to the dock, the resolution is around 1 ms in most cases. For your need, this should be sufficient.
Related
I want to implement the algorithm that awaits for some events and handles them after some delay. Each event has it's own predefined delay. The handler may be executed in a separate thread. The issues with the CPU throttling, the host overload, etc. may be ignored - it's not intended to be a precise real-time system.
Example.
At moment N arrives an event with delay 1 second. We want to handle it at moment N + 1 sec.
At moment N + 0.5 sec arrives another event with delay 0.3 seconds. We want to handle it at moment N + 0.8 sec.
Approaches.
The only straightforward approach that comes to my mind is to use a loop with minimal possible delay inbetween iterations, like every 10 ms, and check if any event on our timeline should be handled now. But it's not a good idea since the delays may vary on scale from 10 ms to 10 minutes.
Another approach is to have a single thread that sleeps between events. But I can't figure out how to forcefully "wake" it when there is a new event that should be handled between now and the next scheduled wake up.
Also it's possible to use a thread per event and just sleep, but there may be thousands of simultanious events which effectively may lead to running out of threads.
The solution can be language-agnostic, but I prefer the C++ STD library solution.
Another approach is to have a single thread that sleeps between events. But I can't figure out how to forcefully "wake" it when there is a new event that should be handled between now and the next scheduled wake up.
I suppose solution to these problems are, at least on *nix systems, poll or epoll with some help of timer. It allows you to make the thread sleep until some given event. The given event may be something appearing on stdin or timer timeout. Since the question was about a general algorithm/idea of algorithm and the code would take a lot of space I am giving just pseudocode:
epoll = create_epoll();
timers = vector<timer>{};
while(true) {
event = epoll.wait_for_event(timers);
if (event.is_timer_timeout()) {
t = timers.find_timed_out();
t.handle_event();
timers.erase(t);
} else if (event.is_incoming_stdin_data()) {
data = stdin.read();
timers.push_back(create_timer(data));
}
}
Two threads that share a priority queue.
Arrivals thread: Wait for arrival. When event arrives calculate time for handler to run. Add handler to queue with priority of handler time ( the top of the queue will be the next event that is to be handled
Handler thread: Is now equal to time of handler at top of queue then run handler. Sleep for clock resolution.
Note: check if your queue is thread safe. If not, then you will have to use a mutex.
This looks simple, but there a lot of gotchas waiting for the inexperienced. So, I would not recommend coding this from scratch. It is better to use a library. The classic is boost::asio. However, this is beginning to show its age and has way more bells and whistles than are needed. So, personally, I use something more lightweight and coded in C++17 - a non blocking event waiter class I coded that you can get from https://github.com/JamesBremner/await. Notice the sample application using this class which does most of what you require https://github.com/JamesBremner/await/wiki/Event-Server
If my timeslice is 3 seconds, I am guessing the alarm stops the execution of a process every three seconds. What does sleep do? Does it put the process to sleep for 3 seconds? This does not make sense to me - what if there are a lot of processes? Wouldn't it have to sleep for longer?
I am doing this with the round robin stimulation:
while (head!=NULL)
{
alarm(TIMESLICE);
sleep(TIMESLICE);
}
cout<<"no processes left"<<endl;
The code works, but I just want to understand what exactly is going on as I am new to this concept.
I am guessing the alarm stops the execution of a process every three seconds.
Sort of. It arranges for a signal to be sent to the process in three seconds. The process can then continue normally and can even ignore the signal if it wants to.
What does sleep do? Does it put the process to sleep for 3 seconds?
Correct.
This does not make sense to me - what if there are a lot of processes? Wouldn't it have to sleep for longer?
No. Even a process that never sleeps isn't guaranteed to get the CPU all the time. A process that isn't sleeping may or may not be scheduled to run on a core at any particular time. Once it's no longer sleeping, it's ready-to-run, and the scheduler will make the decision of when and for how to long to let it use what core.
Kind of C++ and even more Boost noobie here.
I have successfully managed to create two threads, based on this example, one Worker and one Interrupter. The latter sleeps, via this_thread::sleep_for for 50 seconds and interrupts the Worker if he is not done within that time, with proper use of while !this_thread::interruption_requested() and thread::interrupt(). So it's a very nice and easy timeout mechanism. My problem is how to stop Interrupter sleep sooner? I mean if Worker finishes before that 50 seconds, I do a this_thread::yield or this_thread::interruption_requested (both seem to work) but Interrupter is still asleep and have to wait for 50 seconds for him to wake up:(
Is there any way to do this timeout mechanism, but if Worker is done with his work before sleep is over, to notify/wake up Interrupter?
PS: Do I need some sort of synchronization when all are done?
Your interrupter thread should not sleep unconditionally for 50 seconds but wait for conditional variable for 50 seconds, if worker thread finishes earlier it will signal conditional var and interrupter would wake up. You can use either std::conditional_variable or one from boost with the same name
I'm using the GCC compiler and C++ and I want to make a timer that triggers an interruption when the countdown is 0.
Any Ideas? Thanks in advance.
EDIT
Thanks to Adam, I know how to do it.
Now. What about multiple timers running in parallel?
Actually, these timers are for something very basic. In NCURSES, I have a list of things. When I press a key, one of the things will change colors for 5 seconds. If I press another key, another thing in the list will do the same. It's like emphasize strings depending on the user input. Is there a simpler way to do that?
An easy, portable way to implement an interrupt timer is using Boost.ASIO. Specifically, the boost::asio::deadline_timer class allows you to specify a time duration and an interrupt handler which will be executed asynchronously when the timer runs out.
See here for a quick tutorial and demonstration.
One way to do it is to use the alarm(2) system call to send a SIGALRM to your process when the timer runs out:
void sigalrm_handler(int sig)
{
// This gets called when the timer runs out. Try not to do too much here;
// the recommended practice is to set a flag (of type sig_atomic_t), and have
// code elsewhere check that flag (e.g. in the main loop of your program)
}
...
signal(SIGALRM, &sigalrm_handler); // set a signal handler
alarm(10); // set an alarm for 10 seconds from now
Take careful note of the cautions in the man page of alarm:
alarm() and setitimer() share the same timer; calls to one will interfere with use of the other.
sleep() may be implemented using SIGALRM; mixing calls to alarm() and sleep() is a bad idea.
Scheduling delays can, as ever, cause the execution of the process to be delayed by an arbitrary amount of time.
I'm implementing a checking system in C++. It runs executables with different tests. If the solution is not correct, it can take forever for it to finish with certain hard tests. That's why I want to limit the execution time to 5 seconds.
I'm using system() function to run executables:
system("./solution");
.NET has a great WaitForExit() method, what about native C++?. I'm also using Qt, so Qt-based solutions are welcome.
So is there a way to limit external process' execution time to 5 seconds?
Thanks
Use a QProcess with a QTimer so you can kill it after 5 seconds. Something like;
QProcess proc;
QTimer timer;
connect(&timer, SIGNAL(timeout()), this, SLOT(checkProcess());
proc.start("/full/path/to/solution");
timer.start(5*1000);
and implement checkProcess();
void checkProcess()
{
if (proc.state() != QProcess::NotRunning())
proc.kill();
}
Use a separate thread for doing your required work and then from another thread, issue the
pthread_cancle () call after some time (5 sec) to the worker thread. Make sure to register proper handler and thread's cancelability options.
For more details refer to: http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cancel.3.html
Check out Boost.Thread to allow you to make the system call in a separate thread and use the timed_join method to restrict the running time.
Something like:
void run_tests()
{
system("./solution");
}
int main()
{
boost::thread test_thread(&run_tests);
if (test_thread.timed_join(boost::posix_time::seconds(5)))
{
// Thread finished within 5 seconds, all fine.
}
else
{
// Wasn't complete within 5 seconds, need to stop the thread
}
}
The hardest part is to determine how to nicely terminate the thread (note that test_thread is still running).
void WaitForExit(void*)
{
Sleep(5000);
exit(0);
}
And then use it (Windows specific):
_beginthread(WaitForExit, 0, 0);
Solution testing system on Windows should use Job objects to restrict it's access to the system and execution time (not the real time, BTW).
If you are working with Posix compliant systems (of which MacOS and Unix generally are), use fork execv and ``waitpidinstead ofsystem`.An example can be found here. The only really tricky bit now is how to get a waitpid with a timeout. Take a look here for ideas.