Thread overview
How to sleep accurately
Jun 28, 2007
Jason House
Jun 28, 2007
Daniel Giddings
Jun 28, 2007
Jason House
Jun 28, 2007
Daniel Giddings
Jun 28, 2007
Bill Baxter
Jun 28, 2007
BCS
Jun 29, 2007
Jason House
Jul 02, 2007
BCS
June 28, 2007
I've been trying for a while now to get a sleep routine that actually works as I expect it to (sleeping for the time specified within a practical error margin).


Let's say you want to sleep for 0.1 seconds (wall clock).

msleep(100); // Not available under linux

usleep(100000); // Not guaranteed to be reentrant...

timespec ts;
ts.sec = 0;
ts.nsec = 100000000;
nanosleep(ts,cast(timespec)null); // Thread safe


Unfortunately, all of those can be interrupted by signals (such as the garbage collector running).  Ignoring the reentrant issue (which seems to not affect stuff in practice), I tried the following:

time_t now = clock();
time_t stop = now + 100000/CLOCKS_PER_SECOND;
while(now<stop){
  usleep(stop-now);
  now = clock();
}


On windows, that seemed to work.  Under linux, clock() keeps returning zero!  It appears that it returns the process time that elapsed since the last call to clock rather than using any kind of absolute reference and is useless.

Does anyone have a good way of doing this?
June 28, 2007
I'm not sure of the best way to do it but I'm interested in what people think ;-)

You can use gettimeofday under linux instead of clock. It's in std.c.linux.linux.

long getTime() // in ms
{
	timeval t;
	struct_timezone z;

	gettimeofday(&t, &z);

	return t.tv_sec * 1000 + t.tv_usec / 1000;
}


Jason House wrote:
> I've been trying for a while now to get a sleep routine that actually works as I expect it to (sleeping for the time specified within a practical error margin).
> 
> 
> Let's say you want to sleep for 0.1 seconds (wall clock).
> 
> msleep(100); // Not available under linux
> 
> usleep(100000); // Not guaranteed to be reentrant...
> 
> timespec ts;
> ts.sec = 0;
> ts.nsec = 100000000;
> nanosleep(ts,cast(timespec)null); // Thread safe
> 
> 
> Unfortunately, all of those can be interrupted by signals (such as the garbage collector running).  Ignoring the reentrant issue (which seems to not affect stuff in practice), I tried the following:
> 
> time_t now = clock();
> time_t stop = now + 100000/CLOCKS_PER_SECOND;
> while(now<stop){
>   usleep(stop-now);
>   now = clock();
> }
> 
> 
> On windows, that seemed to work.  Under linux, clock() keeps returning zero!  It appears that it returns the process time that elapsed since the last call to clock rather than using any kind of absolute reference and is useless.
> 
> Does anyone have a good way of doing this?
June 28, 2007
Daniel Giddings wrote:
> I'm not sure of the best way to do it but I'm interested in what people think ;-)
> 
> You can use gettimeofday under linux instead of clock. It's in std.c.linux.linux.
> 
> long getTime() // in ms
> {
>     timeval t;
>     struct_timezone z;
> 
>     gettimeofday(&t, &z);
> 
>     return t.tv_sec * 1000 + t.tv_usec / 1000;
> }

Thanks.  I'm using that and it seems to be working well...  I'll have to add some kind of check for the end of the day.  Will this have issues with daylight savings time?  Can I force it to use a timezone without that?
June 28, 2007
I don't thin so, but to be honest I've never tried it. The man page indicates that the timezone field is obsolete and null can be passed:

http://www.rt.com/man/gettimeofday.2.html

Jason House wrote:
> Daniel Giddings wrote:
>> I'm not sure of the best way to do it but I'm interested in what people think ;-)
>>
>> You can use gettimeofday under linux instead of clock. It's in std.c.linux.linux.
>>
>> long getTime() // in ms
>> {
>>     timeval t;
>>     struct_timezone z;
>>
>>     gettimeofday(&t, &z);
>>
>>     return t.tv_sec * 1000 + t.tv_usec / 1000;
>> }
> 
> Thanks.  I'm using that and it seems to be working well...  I'll have to add some kind of check for the end of the day.  Will this have issues with daylight savings time?  Can I force it to use a timezone without that?
June 28, 2007
Jason House wrote:
> Daniel Giddings wrote:
>> I'm not sure of the best way to do it but I'm interested in what people think ;-)
>>
>> You can use gettimeofday under linux instead of clock. It's in std.c.linux.linux.
>>
>> long getTime() // in ms
>> {
>>     timeval t;
>>     struct_timezone z;
>>
>>     gettimeofday(&t, &z);
>>
>>     return t.tv_sec * 1000 + t.tv_usec / 1000;
>> }
> 
> Thanks.  I'm using that and it seems to be working well...  I'll have to add some kind of check for the end of the day.  

"""
The gettimeofday() function shall obtain the current time, expressed as seconds and microseconds since the Epoch, and store it in the timeval structure pointed to by tp. The resolution of the system clock is unspecified.
"""

So no, you don't have to worry about the end of the day, just the end of something like 2^32 or 2^64 seconds from around January 1970, depending on your platform.


--bb
June 28, 2007
Reply to Jason,

> I've been trying for a while now to get a sleep routine that actually
> works as I expect it to (sleeping for the time specified within a
> practical error margin).
> 
> Let's say you want to sleep for 0.1 seconds (wall clock).
> 
> msleep(100); // Not available under linux
> 
> usleep(100000); // Not guaranteed to be reentrant...
> 
> timespec ts;
> ts.sec = 0;
> ts.nsec = 100000000;
> nanosleep(ts,cast(timespec)null); // Thread safe
> Unfortunately, all of those can be interrupted by signals (such as the
> garbage collector running).  Ignoring the reentrant issue (which seems
> to not affect stuff in practice), I tried the following:
> 
> time_t now = clock();
> time_t stop = now + 100000/CLOCKS_PER_SECOND;
> while(now<stop){
> usleep(stop-now);
> now = clock();
> }
> On windows, that seemed to work.  Under linux, clock() keeps returning
> zero!  It appears that it returns the process time that elapsed since
> the last call to clock rather than using any kind of absolute
> reference and is useless.
> 
> Does anyone have a good way of doing this?
> 

if you are on x86 and if you can get the clock speed and if you don't mind asm you can get a clock cycle resolution busy wait using:

|long first,stop;
|asm
|{
|  rdtsc;
|  mov first, EAX;
|  mov 4+first, EDX;
|}
|
|stop = first + TimeInCPUCycles();
|
|while(first < stop)
|  asm
|  {
|    rdtsc;
|    mov first, EAX;
|    mov 4+first, EDX;
|  }


June 29, 2007
BCS wrote:
> if you are on x86 and if you can get the clock speed and if you don't mind asm you can get a clock cycle resolution busy wait using:


I'm trying to stay as cross platform as possible.  It's currently used on x86 and mac.  I'm discovering that gettimeofday is not available on the mac.  I still have to find another solution.
July 02, 2007
Reply to Jason,

> BCS wrote:
> 
>> if you are on x86 and if you can get the clock speed and if you don't
>> mind asm you can get a clock cycle resolution busy wait using:
>> 
> I'm trying to stay as cross platform as possible.  It's currently used
> on x86 and mac.  I'm discovering that gettimeofday is not available on
> the mac.  I still have to find another solution.
> 

well if you are using x86 mac you would be potable and PPC has a similar CPU clock counter. But you would still need something else for any other system.