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.
Related
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 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.
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.
I want to refresh and have control of time interval changes. Most people only have an infinite loop constantly polling the time from time.h and wasting cycles. There is a way to get clock changes without disturbing too much the system? I am using c/c++ and really want to learn how to do this manually only using linux libraries. Most programs need the notion of time.
I want to be notified of system clock updates. I am trying to do a scientific app that responds in real time. Sleep() and thing like that only let me specify a time delay starting from the execution of that statemen. Localtime() and string returning times from the c header only give me the specific time when was executed. If I use it this time is too late, it had elapsed too many nanoseconds.
Read the time(7) man pages to understand how to use the system calls gettimeofday(2), setitimer(2), clock_gettime(2), timer_create(2) etc... and library functions (strftime, localtime, ...) related to time.
If you want to code an application recieving timer events, learn about timers and e.g. SIGALRM signal. Read first signal(7)
But you really should read e.g. Advanced Unix Programming and Advanced Linux Programming and understand what are syscalls
You might want to use poll(2) for polling or for waiting.
The most basic approach that's also portable and compatible with most other tasks is select. It sleeps until a certain amount of time elapses or a file becomes ready for I/O, which gives you a way to update the task list before the next task occurs. If you don't need interruption capability, you can just use sleep (or usleep).
I have a thread running on a Linux system which i need to execute in as accurate intervals as possbile. E.g. execute once every ms.
Currently this is done by creating a timer with
timerfd_create(CLOCK_MONOTONIC, 0)
, and then passing the desired sleep time in a struct with
timerfd_settime (fd, 0, &itval, NULL);
A blocking read call is performed on this timer which halts thread execution and reports lost wakeup calls.
The problem is that at higher frequencies, the system starts loosing deadlines, even though CPU usage is below 10%. I think this is due to the scheduler not waking the thread often enough to check the blocking call. Is there a command i can use to tell the scheduler to wake the thread at certain intervals as far as it is possble?
Busy-waiting is a bad option since the system handles many other tasks.
Thank you.
You need to get RT linux*, and then increase the RT priority of the process that you want to wake up at regular intervals.
Other then that, I do not see problems in your code, and if your process is not getting blocked, it should work fine.
(*) RT linux - an os with some real time scheduling patches applied.
One way to reduce scheduler latency is to run your process using the realtime scheduler such as SCHED_FIFO. See sched_setscheduler .
This will generally improve latency a lot, but still theres little guarantee, to further reduce latency spikes, you'll need to move to the realtime brance of linux, or a realtime OS such as VxWorks, RTEMS or QNX.
You won't be able to do what you want unless you run it on an actual "Real Time OS".
If this is only Linux for x86 system I would choose HPET timer. I think all modern PCs has this hardware timer build in and it is very, very accurate. I allow you to define callback that will be called every millisecond and in this callback you can do your calculations (if they are simple) or just trigger other thread work using some synchronization object (conditional variable for example)
Here is some example how to use this timer http://blog.fpmurphy.com/2009/07/linux-hpet-support.html
Along with other advice such as setting the scheduling class to SCHED_FIFO, you will need to use a Linux kernel compiled with a high enough tick rate that it can meet your deadline.
For example, a kernel compiled with CONFIG_HZ of 100 or 250 Hz (timer interrupts per second) can never respond to timer events faster than that.
You must also set your timer to be just a little bit faster than you actually need, because timers are allowed to go beyond their requested time but never expire early, this will give you better results. If you need 1 ms, then I'd recommend asking for 999 us instead.