
On 24 Jan 2015 at 21:29, Andrey Semashev wrote:
The problem with the above strategy is that it was clearly designed around when Windows had a fixed tick interval of 10ms multiples, the kernel didn't coalesce timers and the kernel wasn't tickless.
I'm not sure if that was done so in account for a specific time quant duration. My understanding is that this was mainly done for two reasons. First, to make shorter waits more efficient.
I can see that. Right now it creates a brand new waitable timer object every single timed wait if the interval >= 20 ms. I would lazy initialise and cache one in thread local data instead.
Second, waitable timers take into account system time shifts, which is more important for longer waits.
They _optionally_ do yes. They can do relative as well as absolute waits, and if the value was absolute then it is adjusted for system clock shifts. Thread already has support for this.
FWIW, as I remember Windows quant duration is adjustable both by user and application and by default on desktop is about 15 ms. So it makes little sense to aim for a specific quant value, much less a multiple of 10 ms.
The quant can be reduced to 0.9 ms, or be anywhere between 0.9 and ~15 ms and can change at any time.
The optimization for shorter waits may not be relevant anymore, but in order to make the change for use of waitable timers for all absolute waits one should conduct some performance tests.
Agreed.
And there's another consideration. Waitable timers are useful for absolute waits. For relative waits I would still like Boost.Thread to use relative system waits. The reason is that relative waits do not react to system time shifts and do not require a waitable timer kernel object.
This is interesting actually. The win32 interruptible_wait() and uninterruptible_wait() functions consume a detail::timeout which is capable of transferring either relative or absolute timeout. However condition_variable timed wait and thread timed join never calls with anything but an absolute deadline timeout, and converts all relative to absolute. Oddly enough this_thread::sleep_until seems to convert its absolute timeout to a relative one, and thunks through this_thread::sleep_for, so here all absolutes are converted to relative. So we have the odd situation that condition_variable and thread join are always implemented as absolute timeouts, while thread sleep is always implemented as relative timeouts. I also see that timed mutex always converts absolute to relative too on win32. Some of this isn't win32 specific either. I can see some code there which looks like these are decisions being made by upper layers of code and so would affect POSIX as well. I've added this issue as https://svn.boost.org/trac/boost/ticket/10967. Some references to code: Always uses absolute: https://github.com/boostorg/thread/blob/develop/include/boost/thread/w in32/condition_variable.hpp#L92 Always uses relative: https://github.com/boostorg/thread/blob/develop/include/boost/thread/w in32/basic_timed_mutex.hpp#L190 Always uses relative: https://github.com/boostorg/thread/blob/develop/include/boost/thread/v 2/thread.hpp#L60 Always uses absolute: https://github.com/boostorg/thread/blob/develop/include/boost/thread/d etail/thread.hpp#L551
What I'm planning to do is very simple: we always use deadline timer scheduling from now on, so quite literally the steady_clock deadline that comes in is exactly that handed to Windows unmodified. I was also going to try setting a tolerable delay via SetWaitableTimerEx() on Vista and later where the tolerable delay is calculated as 10% of the interval to the deadline but clamped to:
timeGetTime() <= tolerable delay <= 250 ms
I'm not sure I understood this. timeGetTime() returns system time since boot. Did you mean that you would somehow discover the quant duration and use it for the tolerable delay?
Sorry I was being sloppy. The current quantum is the KiCyclesPerClockQuantum kernel variable. I believe there is a user space function for that now ... a quick google search says GetSystemTimeAdjustment(). He literally reads from a memory location in the kernel, so it's as quick as reading a variable. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/