I have written some service using C++, QT and boost.
I need some function run in given time (for maintance purposes).
The only method I have worked as expected is to pool current time in thread.
I've try to use boost method:
boost::asio::io_service io_service;
boost::asio::deadline_timer timer (io_service);
boost::gregorian::date day = boost::gregorian::day_clock::local_day();
boost::posix_time::time_duration time = boost::posix_time::duration_from_string(START_TIME);
boost::posix_time::ptime expirationtime ( day, time );
timer.expires_at (expirationtime);
timer.async_wait (boost::bind(func, param1, param2));
io_service.run();
This works for today if I don't change system time. But if I try to set it for tommorow (or any other day in future), for example, and change system time to test it - it doesn't fire (it's count miliseconds after async_wait call?)
Is there any other methods beside time pooling to start task in given day and time (NOT time interval)?
Instead of periodic polling, you can use std::this_thread::sleep_until.
According to the description on cppreference.com this will take subsequent clock adjustments into account:
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.
However, this is new as of C++11. If your compiler doesn't support that, you may need to poll. Unless there is other library support depending on your OS. Also, sleep_until might be using polling internally (or it is cleverly waking up and reconfiguring if the clock changes).
As mentioned in comments, your problem is more commonly solved externally (invoking your process on schedule) via cron on Unix-style systems (including Mac OS X), or Task Scheduler on Windows. Such external invocations are more robust when it comes to potential failures of your task.
Related
I want to use async functions calling. I chose boost::deadline_timer.
For me, hardware-timer is a specific hardware (surprisingly), that works independently from CPU and is duty only for monitoring time. At the same time, if I understand correctly, it is also can be used for setting timeout and generating an interrupt when the timeout has been reached. (timers)
The primary advantage of that is asynchronous execution. The thread that set a timer can continue working and the callback function will be triggered in the same thread where the timer has been set.
Let me describe as I see it in action.
The application contains one or more worker threads. E.g. they process input items and filter them. Let's consider that application has 5 threads and each thread set one timer (5 seconds).
Application is working. E.g. current thread is thread-3.
Timer (thread-0) has been expired and generates (probably the wrong term) an interrupt.
Thread-context switching (thread-3 -> thread-0);
Callback function execution;
Timer (thread-1) has been expired and generates interruption.
...
And so on
P.S.0. I understand that this is not only one possible case for multi-threaded application.
Questions:
Did I describe the working process rightly?
Do I understand correctly that even current thread is thread-0 it also leads to context-switching, since the thread has to stop to execute current code and switch to execute the code from callback fuction?
If each thread sets 100k or 500k timers how it will affect on performance?
Does hardware have the limit to count of timers?
How expensive to update the timeout for a timer?
A hardware timer is, at its core, just a count-up counter and a set of comparators (or a count-down counter that uses the borrow of the MSb as an implicit comparison with 0).
Picture it as a register with a specialized operation Increment (or Decrement) that is started at every cycle of a clock (the easiest kind of counter with this operation is the Ripple-counter).
Each cycle the counter value is also fed to the comparator, previously loaded with a value, and its output will be the input to the CPU (as an interrupt or in a specialized pin).
In the case of a count-down counter, the borrow from the MSb acts as the signal that the value rolled over zero.
These timers have usually more functions, like the ability to stop after they reach the desired value (one-shot), to reset (periodic), to alternate the output state low and high (square wave generator), and other fancy features.
There is no limit on how many timers you can put on a package, of course, albeit simple circuits, they still have a cost in terms of money and space.
Most MCUs have one or two timers, when two, the idea is to use one for generic scheduling and the other for high-priority tasks orthogonal to the OS scheduling.
It's worth noting that having many hardware timers (to be used by the software) is useless unless there are also many CPUs/MCUs since it's easier to use software timers.
On x86 the HPET timer is actually made of at most 32 timers, each with 8 comparators, for a total of 256 timers as seen from the software POV.
The idea was to assign each timer to a specific application.
Applications in an OS don't use the hardware timers directly, because there can possibly be a lot of applications but just one or two timers.
So what the OS does is share the timer.
It does this by programming the timer to generate an interrupt every X units of time and by registering an ISR (Interrupt Service Routine) for such an event.
When a thread/task/program sets up a timer, the OS appends the timer information (periodic vs one-shot, period, ticks left, and callback) to a priority queue using the absolute expiration time as the key (see Peter Cordes comments below) or a list for simple OSes.
Each time the ISR is called the OS will peek at the queue and see if the element on top is expired.
What happens when a software timer is expired is OS-dependent.
Some embedded and small OS may call the timer's callback directly from the context of the ISR.
This is often true if the OS doesn't really have a concept of thread/task (and so of context switch).
Other OSes may append the timer's callback to a list of "to be called soon" functions.
This list will be walked and processed by a specialized task. This is how FreeRTOS does it if the timer task is enabled.
This approach keeps the ISR short and allows programming the hardware timer with a shorter period (in many architectures interrupts are ignored while in an ISR, either by the CPU automatically masking interrupts or by the interrupt controller).
IIRC Windows does something similar, it posts an APC (Async Procedure Call) in the context of the thread that set the software timer just expired. When the thread is scheduled the APC will (as a form of a window's message or not, depending on the specific API used) call the callback. If the thread was waiting on the timer, I think it is just set in the ready state. In any case, it's not scheduled right away but it may get a priority boost.
Where the ISR will return is still OS-dependent.
An OS may continue executing the interrupted thread/task until it's scheduled out. In this case, you don't have step 4 immediately after step 3, instead, thread3 will run until its quantum expires.
On the other way around, an OS may signal the end of the ISR to the hardware and then schedule the thread with the callback.
This approach doesn't work if two or more timers expire in the same tick, so a better approach would be to execute a rescheduling, letting the schedule pick up the most appropriate thread.
The scheduling may also take into account other hints given by the thread during the creation of the software timer.
The OS may also just switch context, execute the callback and get back to the ISR context where it continues peeking at the queue.
The OS may even do any of that based on the period of the timer and other hints.
So it works pretty much like you imagined, except that a thread may not be called immediately upon the timer's expiration.
Updating a timer is not expensive.
While all in all the total work is not much, the timer ISR is meant to be called many many times a second.
In fact, I'm not even sure an OS will allow you to create such a huge number (500k) of timers.
Windows can manage a lot of timers (and their backing threads) but probably not 500k.
The main problem with having a lot of timers is that even if each one performs little work, the total work performed may be too much to keep up with the rate of ticking.
If each X units (e.g. 1ms) of time 100 timers expire, you have X/100 units of time (e.g. 10us) to execute each callback and the callback's code may just be too long to execute in that slice of time.
When this happens the callbacks will be called less often than desired.
More CPU/cores will allow some callback to execute in parallel and would alleviate the pressure.
In general, you need different timers if they run at different rates, otherwise, a single timer that walks a data structure filled with elements of work/data is fine.
Multi-threading can provide concurrency if your tasks are IO-bounded (files, network, input, and so on) or parallelism if you have a multi-processor system.
The problem
I'm trying to use a simple, portable way to perform an interruptible sleep for a thread. Another requirement I have is about the use of SIGSTOP/SIGCONT, if the program is suspended the wait must performs without taking into account the suspension. Example: I'm waiting for 5 seconds, after 1 second the program is suspended, after 1 one minute is restored, the wait should run again waiting 4 seconds.
My analisys
std::condition_variable::wait_for() and std::condition_variable::wait_until() methods use a monothonic time only starting from gcc 10 and glibc 2.6 bugzilla. On previous versions or where there's no platform support, i.e. pthread_cond_clockwait() not available, the system clock is used. Using the system clock however can have side effects like a timeout too early or too late if the system clock is changed by human or automatically (ex. NTP). In addition the wait_for() and wait_until() can trigger too early if we stop the process via SIGSTOP because the system clock or steady clock are evaluated again and since the whole time is running but our process is frozen, when we start the process again using SIGCONT every wait is triggered.
Possible solutions
It seems there's only one way to sleep in a reliable way even on older platforms, calling select system call. In addition select behavior is ok for my requirements and it can be interrupted using the self pipe trick for example.
The question
Is my analysis correct? Am I missing anything?
I have several objects I need to maintain with time-to-live parameters, and trigger some kind of event when they time out.
Implementing this as a timer that just waits for a the object with the smallest TTL before popping it off a queue doesn't seem very efficient because I need to be able to add/remove objects sporadically from this queue (and they can have any time out value), possibly before they time out. For example, ugly things would happen if I think that the shortest TTL object is 10 seconds and block the timeout thread for 10 seconds, but during this period an object with 3 seconds to live is added to the queue.
The naive way of doing
while (true) {
update()
}
void update() {
// get delta since last call to update()
// subtract delta from each object and time out if ttl < 0
}
is pretty slow since there is a lot of memory being shuffled around for the sole purpose of updating ttl on microsecond resolution.
Is there a good way to do this without creating a separate thread for each object?
I have access to the C++11 std lib but no boost or any external libraries.
One easy but somewhat crappy option is to poll for updates to the queue - say every second or tenth of a second. Too often and your OS may not have time to yield for some productive work; too infrequently and your timing capability becomes very crude. You can use std::this_thread::sleep_for(std::chrono::milliseconds(n)) for the inter-poll delay, or may want to use e.g. select if you are doing other I/O too. You can have any accesses to the queue arbitrated by a mutex, and use say a std::map<std::chrono::time_point, Task> to keep Tasks sorted by TTL, so each time the poll period expires you just iterate from .begin() towards .end(), exiting early if the time_point has not elapsed yet.
...without creating a separate thread for each object?
The above can be done is a single background thread if desired.
Another option: a non-Standard OS-provided asynchronous notification mechanism such as a signal-raising alarm... e.g. alarm, but your signal is typically only allowed to do a fairly restricted number of operations though, the normal advice is to set a flag so the interrupted thread can know there's work for it to do - that's not much different to having to check the queue for expired Tasks anyway, but the advantage is the signal itself can force some blocking operations to terminate early (e.g. without SA_RESTART flag to sigaction), with error codes indicating the reason for the interruption. Decades ago I came across some blocking operations on some Operating Systems that had limited guarantees about the state of I/O buffers the interrupted routine may have been using, making it impossible to build a robust resumption of that I/O - check your OS docs.
As could be read at:
https://svn.boost.org/trac/boost/ticket/3504
a deadline_timer that timeouts periodically and which is implemented using deadline_timer::expires_at() (like the example in Boost Timer Tutorial, 3th example) will probably fail if the system time is modified (for example, using the date command, if your operating system is Linux).
Is there a simple and appropiate way of performing this operation now, using Boost? I do not want to use deadline_timer::expires_from_now() because I could verify that it is less accurate than "manually" updating the expiry time.
As a temporal solution I decide to, before setting a new expires_at value, calculate the time period between now() and expires_at(). If it is more than double the periodic delay, then I exceptionally use expires_from_now() to resync with the new absolute time.
In Boost 1.49+, Boost.Asio provides steady_timer. This timer uses chrono::steady_clock, a monotonic clocks that is not affected by changes to the system clock.
If you cannot use Boost 1.49+, then checking the timers or clocks for changes is a reasonable alternative solution. While it is an implementation detail, Boost.Asio may limit the amount of time spent waiting on an event in its reactor, so that it can periodically detect changes to system time. For example, the reactor implementation using epoll will wait a maximum of 5 minutes. Thus, without forcing an interrupt on the reactor (such as setting a new expiration time on a timer), it can take Boost.Asio up to 5 minutes before detecting changes to system time.
A long time ago I had a bug in my program. The root cause was that the C function
sleep(60);
would on rare occasions sleep less than 60 seconds. Or the function did cause the thread to sleep more than 60 s, but the clock was changed automatically by the OS (this seems likely since bug was happening only on XX::00::00), aka it was manifesting itself rarely, and only on "round hour" (sleep shoudl have ended at >xh0m0s, it ended on x-1h59m59.99*s).
Then my project manager went on a rant how he said million times that we should only use timers, not sleep.
From that time I accepted the notion that timers are more accurate than sleep(), but now I feel that I should ask for some more authoritative source.
So :
are timers more precise than sleep?
(related) are they deep down(on the OS level) implemented using different methods?
I know timers are used to do callbacks, sleep just delays execution of current thread, Im talking about delay execution part of the implementation.
BTW OS was Linux, but I care about general answer if possible.
Timers are definitely more accurate than sleep. Sleep is meant as just a rough measure of how long until the task scheduler revives a thread or process. Changes to the system clock, an overloaded task scheduler etc. will affect how long sleep actually sleeps for.
A timer will measure time more accurately. Generally speaking a timer will measure time accurately. There are two kinds of timers - ones based on the system clock like the functions in "time.h". Those will be affected by stuff like changes to the system clock. For example - if you change the system time, switch from daylight savings time, or suspend the machine etc. the actual measured time may be different from the real time.
The other kind of clocks are high resolution timers that are based on CPU ticks. These are timers like QueryPerformanceTimer on windows, and clock_gettime() on linux. These simply count cpu cycles. They won't be affected by changes to the system timer - but they will deviate from real world time in two ways:
Time will skew over long periods because the clock resolution is not exact such that over long periods measuring time this way will cause cpu time to drift from real time.
If the machine is suspended the CPU stops and the timer will not account for this.
What you want to do is sleep for a much shorter amount of time and use the clock that has the appropriate resolution. Eg. if you need to sleep for less than a few minutes, you should use high resolution timers. Sleep 100x more often than you need to and check elapsed time every time sleep comes back to see if the right amount of time has elapsed. If you need to sleep for more than a few minutes do the same but with the functons in time.h to check elapsed time.
If you need to be 100% accurate with time you may need specialized hardware- or to check real time periodically against an online time server - like the navy's atomic clock. ( http://tycho.usno.navy.mil/ntp.html)
There is no general answer for the simple reason that there is nothing in either the C or C++ standard that provides the ability to put an application to sleep. So the discussion is inherently going to be OS-dependent.
The unix sleep() function has a coarse granularity. There's also usleep() and nanosleep() which have much finer granularity. The function select() can also be used to put an application to sleep. Simply specify a timeout and no file descriptors.
Note #1: The interaction between sleep(), usleep(), nanosleep(), itimers, and alarms is unspecified.
Note #2: Don't expect any of these mechanisms to have the precision of an atomic clock.