Re: [Boost-users] [thread] bug: thread::sleep can't 'Idle'
Actually - I just tried to rtfm to find the relevant part, and it is
less than obvious given the rather terse description of xtime as a time
or a duration. I don't think anything in boost.threads uses xtime as a
duration (any more - since about 2001)?
________________________________
From: boost-users-bounces@lists.boost.org
[mailto:boost-users-bounces@lists.boost.org] On Behalf Of Darryl Green
Sent: Wednesday, 11 October 2006 4:48 PM
To: boost-users@lists.boost.org
Subject: Re: [Boost-users] [thread] bug: thread::sleep can't
'Idle'
Hi Daniel,
boost::thread:sleep takes a time, not a duration. For details,
rationale etc rtfm.
________________________________
From: boost-users-bounces@lists.boost.org
[mailto:boost-users-bounces@lists.boost.org] On Behalf Of Daniel Winsor
Sent: Wednesday, 11 October 2006 4:40 PM
To: boost-users@lists.boost.org
Subject: [Boost-users] [thread] bug: thread::sleep can't
'Idle'
#include
"Darryl Green"
Actually - I just tried to rtfm to find the relevant part, and it is less than obvious given the rather terse description of xtime as a time or >a duration. I don't think anything in boost.threads uses xtime as a duration (any more - since about 2001)?
I've been using Boost.Thread since 1.27 (IIRC) and never wanted to suspend a thread until a specific clock time. I've always had to go through the hassle of getting the current time, adding the brief time I wanted the thread to sleep (watch out for wraps in the xtime members!) and then call thread::sleep. Out of curiosity, who actually prefers using clock times for thread::sleep()? IIRC the implementation still converts the UTC time into a relative time before entering sleep, so it's only misleading to have an absolute time as parameter to sleep. Just my 0.02EUR. // Johan
On Wed, 11 Oct 2006 11:51:10 -0200, Johan Nilsson
"Darryl Green"
wrote in message news:F8DFD2A4C14B454E9DC35640BC72076A9500DF@BRISBANEMAIL1.brisbane.tabq.com... Actually - I just tried to rtfm to find the relevant part, and it is less than obvious given the rather terse description of xtime as a time or >a duration. I don't think anything in boost.threads uses xtime as a duration (any more - since about 2001)?
I've been using Boost.Thread since 1.27 (IIRC) and never wanted to suspend a thread until a specific clock time. I've always had to go through the hassle of getting the current time, adding the brief time I wanted the thread to sleep (watch out for wraps in the xtime members!) and then call thread::sleep.
Out of curiosity, who actually prefers using clock times for thread::sleep()? IIRC the implementation still converts the UTC time into a relative time before entering sleep, so it's only misleading to have an absolute time as parameter to sleep.
FWIW, I agree with you. Bruno
Johan Nilsson wrote:
Out of curiosity, who actually prefers using clock times for thread::sleep()? IIRC the implementation still converts the UTC time into a relative time before entering sleep, so it's only misleading to have an absolute time as parameter to sleep.
You would need to ask the pthreads folks. ;-) This behaviour is inherited from there. Roland
What about adding a function boost::sleep_until() that takes a point in time and change boost::sleep() to take a duration? Sascha Roland Schwarz wrote:
Johan Nilsson wrote:
Out of curiosity, who actually prefers using clock times for thread::sleep()? IIRC the implementation still converts the UTC time into a relative time before entering sleep, so it's only misleading to have an absolute time as parameter to sleep.
You would need to ask the pthreads folks. ;-) This behaviour is inherited from there.
Roland
Sascha Seewald wrote:
What about adding a function boost::sleep_until() that takes a point in time and change boost::sleep() to take a duration?
I believe the choice was done deliberately, and is more generic. Altough you might not see much use for it, it will allow creating predictable behavior. In the case where you have more complicated timeout scheme only having relative sleep could be a problem. Lets take an example: You have to maintain a task that is started every 10 seconds. Now if you are doing this as: while(true) { ... do something ... relative_sleep(10); } you can see easily that you will accumulate an error from each run of the loop. boost::xtime xt; boost::xtime_get(xt); xt.sec += 10; while(true) { ... do something ... boost::thread::sleep(xt); xt.sec += 10; } you can see now that this works smoothly (of course ... do something ... will be assumed to last < 10 sec) You can always easily write a little relative sleep if you need along the lines: void sleep(int sec) { boost::xtime xt; boost::xtime_get(xt); xt.sec += sec; boost::thread::sleep(xt); } Please don't forget: the threading library supply you with the essential primitives. You might always need to create other convenience functions if needed. You cannot get the behaviour from the example when only a relative sleep is available. Does this make sense to you? Roland
Roland Schwarz wrote:
Sascha Seewald wrote:
What about adding a function boost::sleep_until() that takes a point in time and change boost::sleep() to take a duration?
I believe the choice was done deliberately, and is more generic. Altough you might not see much use for it, it will allow creating predictable behavior.
The problem is, that in most cases boost::sleep() converts the absolute time into a relative time anyway, and this is a race condition (if the thread is interrupted after retrieving the current time, but before the relative duration is calculated, you end up sleeping too long). You can convert a relative time into an absolute time safely, but not the other way around. Maybe this doesn't matter for sleep(), if you can't (or don't need to) distinguish between a thread sleep()ing and a thread that is preempted. [snip example where absolute time sleep is used]
You can always easily write a little relative sleep if you need along the lines:
void sleep(int sec) { boost::xtime xt; boost::xtime_get(xt); xt.sec += sec; boost::thread::sleep(xt); }
Right. But the opposite applies too: given a relative sleep function you can write an absolute sleep just as easily (with the caveat that there is a race condition and you might sleep too long) - which is exactly what boost::thread::sleep() does most of the time anyway.
Please don't forget: the threading library supply you with the essential primitives. You might always need to create other convenience functions if needed. You cannot get the behaviour from the example when only a relative sleep is available.
Well, if you really cared about getting an accurate absolute sleep it would be in the context of a condition variable timed wait, in which case sleep() is not the right function anyway. The primitive in this case is some variant of the operating system sleep system call, which AFAIK always takes a relative time. Cheers, Ian McCulloch
Ian McCulloch wrote:
The problem is, that in most cases boost::sleep() converts the absolute time into a relative time anyway,
This is an implementation detail (of an admittedly bogus implementation).
and this is a race condition (if the thread is interrupted after retrieving the current time, but before the relative duration is calculated, you end up sleeping too long).
This is the outcome of the implementation. But view it as an approximation to the ideal.
You can convert a relative time into an absolute time safely, but not the other way around.
No, the same reasoning that you have done applies, simply you might sleep too short. I am sort of convinced, that both functions need be available, to be able to express intended meaning. (Implementaion details aside). However a little doubt remains, that it will be possible to implement relative waits at all. Which is the reference point from where on relative time will be measured? Function invocation? Will not be implementable -> preemption between invocation and opsys call. But I have to admit that the same applies to absolute time, since the thread might be preempted between scheduler wake up and time when the boost::sleep will return. Altough it is less likely that we will be preempted anytime too soon after just having got a time sclice from the scheduler. Interface extension possibly as an overload: sleep(long sec, long nsec) which will mean to do a relative sleep, and translates to the operating systems native meaning of sleep. I'll put this into the list of TODO's.
Well, if you really cared about getting an accurate absolute sleep it would be in the context of a condition variable timed wait, in which case sleep() is not the right function anyway. The primitive in this case is some variant of the operating system sleep system call, which AFAIK always takes a relative time.
I am afraid this is true. :-( But having a sleep that will wait for absolute time is a need to have. (Or you will need to emulate it by timed_wait on a condition) Btw.: xtime for long has been recognized as a candidate to be replaced by a better time function anyways. We certainly will need a kind of monotonic time too. Where I do see the real problems is, as you have pointed out, that it will be very hard to convince a operating system scheduler to wake up a thread at absolute time. Roland
Roland Schwarz wrote:
No, the same reasoning that you have done applies, simply you might sleep too short.
Not true. By giving sleep() a relative time, I want sleep() to return after that time (plus some, due to delay in getting a timeslice). Now, if the OS API requires an absolute time, sleep() needs to convert to absolute. If it is interrupted between calculating that absolute time and the OsSleep(), it just sleeps in preemption instead of OsSleep. Sebastian Redl
Roland Schwarz wrote: [snip]
while(true) { ... do something ... relative_sleep(10);
}
you can see easily that you will accumulate an error from each run of the loop.
boost::xtime xt; boost::xtime_get(xt); xt.sec += 10; while(true) { ... do something ... boost::thread::sleep(xt); xt.sec += 10; }
you can see now that this works smoothly (of course ... do something ... will be assumed to last < 10 sec)
Perhaps, but this method is susceptible to race conditions. System time can (naturally) get changed by e.g. ntpd or Windows Time at any point - including between xt.sec += 10 and thread::sleep() above, as well as during the actual sleep.
You can always easily write a little relative sleep if you need along the lines:
void sleep(int sec) { boost::xtime xt; boost::xtime_get(xt); xt.sec += sec; boost::thread::sleep(xt); }
And if you like to sleep for less than 1 sec, you'll also need to manipulate the nsec member. Not really hard to fix, but another potential source for bugs. Overloading sleep to allow using date_time's posix_time and time_duration as well as xtime would be an alternative.
Please don't forget: the threading library supply you with the essential primitives. You might always need to create other convenience functions if needed. You cannot get the behaviour from the example when only a relative sleep is available.
That is true, but allowing a time_duration or being able to call e.g. thread::sleep(xt, TIME_RELATIVE) would certainly make things easier. / Johan
Roland Schwarz wrote:
Please don't forget: the threading library supply you with the essential primitives. You might always need to create other convenience functions if needed.
I see your arguments. But I still think duration-based sleep should be part of Boost.Thread. Most of the time I prefer relative sleep over absolute sleep simply because it's a one-liner and sufficient for my all-day-need. I agree with you that absolute sleep is indispensable in certain situations. Therefor Boost.Thread should provide *both* interfaces. Boost.Filesystem provides some convenience functions in convenience.hpp. Maybe something similar in Boost.Thread would be the right place for this? Cheers Sascha
Roland Schwarz wrote:
Please don't forget: the threading library supply you with the essential primitives. You might always need to create other convenience functions if needed. You cannot get the behaviour from the example when only a relative sleep is available.
This isn't quite true for this specific case. It isn't entirely correct to say that absolute waits are a basic primitive, while relative waits are a convenience. Both are basic primitives; sometimes an absolute timeout better fits the problem, and sometimes the opposite is true. In addition, sometimes the underlying implementation emulates absolute timeouts on top of relative timeouts, sometimes the opposite is true. You can emulate the behavior from the example with relative timeouts as long as you have access to the current time of the clock by which the absolute time is measured. Preemptions aren't an issue specific to relative timeouts since a wait with an absolute timeout can as easily be preempted on the way out as a relative wait on the way in. It's clear that our current xtime mechanism is only a stop-gap measure; unfortunately, nobody has proposed a well thought-out alternative (so far). The C++ committee will have to address the issue one way or the other, though, and there isn't much time left. There is some rationale for POSIX's decision to go with the absolute timeout option in http://www.opengroup.org/onlinepubs/009695399/xrat/xsh_chap02.html A previous section also addresses the monotonic clock.
Peter Dimov wrote:
This isn't quite true for this specific case. It isn't entirely correct to say that absolute waits are a basic primitive, while relative waits are a convenience. Both are basic primitives;
I already perceived this, as you can see from another post. Altough I still think that implementing a "true" relative wait/sleep is a nontrivial task. This might conceptually not be too problematic for sleep, but certainly is for wait, since one need to compensate for spurious wakeups.
Preemptions aren't an issue specific to relative timeouts since a wait with an absolute timeout can as easily be preempted on the way out as a relative wait on the way in.
Hmm, sure? I mean "as easily"? I think the probability of being preempted short after having got a time slice from the scheduler is smaller than in the average. (Assuming equal thread priorities.) So one could reason that the way out is more "stable" than the way in. What do you think?
There is some rationale for POSIX's decision to go with the absolute timeout option in
http://www.opengroup.org/onlinepubs/009695399/xrat/xsh_chap02.html
Thank you for the pointer. Interesting is the assumption this document draws about the expected usage of relative times: "When these functions are given relative timeouts, the timeouts are typically for error recovery purposes and need not be so precise." Roland
Roland Schwarz wrote:
Peter Dimov wrote:
Preemptions aren't an issue specific to relative timeouts since a wait with an absolute timeout can as easily be preempted on the way out as a relative wait on the way in.
Hmm, sure? I mean "as easily"? I think the probability of being preempted short after having got a time slice from the scheduler is smaller than in the average. (Assuming equal thread priorities.) So one could reason that the way out is more "stable" than the way in.
Yes, you are right. It's much less probable.
Roland Schwarz wrote:
Johan Nilsson wrote:
Out of curiosity, who actually prefers using clock times for thread::sleep()? IIRC the implementation still converts the UTC time into a relative time before entering sleep, so it's only misleading to have an absolute time as parameter to sleep.
You would need to ask the pthreads folks. ;-) This behaviour is inherited from there.
Roland
That is kinda misleading. pthreads doesn't have a native sleep function. There were proposals for one, and some systems have a non-standard extension, but the usual way is to just call nanosleep(). In boost::threads, almost all of the code paths do in fact convert the absolute time into a relative duration. The only path that doesn't is when there is no nanosleep() and no pthread_delay_np() present; then the sleep is implemented by a pthread_cond_timedwait() which uses an absolute time, which has a resonable rationale for doing so. The rationale for using absolute times in a condition variable wait don't apply to sleep(), IMHO. The pthreads sleep extension uses relative time. There are alternatives to pthread_cond_timedwait() that don't use absolute time, for example select(). So a relative sleep is certainly implementable. Cheers, Ian McCulloch
Ian McCulloch wrote:
.... So a relative sleep is certainly implementable.
Of course, that is the easy part. ;-) It is more challenging to provide a sleep that indeed will wait for absolute time. That function, as you can see from my other post has some advantages which are missing from relative sleep. And the library provided primitives should be the most generic ones. Roland
participants (8)
-
Bruno Martínez
-
Darryl Green
-
Ian McCulloch
-
Johan Nilsson
-
Peter Dimov
-
Roland Schwarz
-
Sascha Seewald
-
Sebastian Redl