www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Thread.sleep (DMD 2.020)

reply John C <johnch_atms hotmail.com> writes:
I think Thread.sleep, which was introduced in core.thread in 2.020, is broken
on Win32. No matter what value I pass to the function, it merely sleeps for 1
millisecond. Looks like the problem is here:

  period = period < TICKS_PER_MILLI ? 
    1 : // <------------------------------------------------- BUG?
    period / TICKS_PER_MILLI;

Should it be testing if period is greater than MAX_SLEEP_MILLS, rather than
less than TICKS_PER_MILLI?

Should I file a bug report?

John
Nov 01 2008
next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
John C wrote:
 I think Thread.sleep, which was introduced in core.thread in 2.020, is broken
on Win32. No matter what value I pass to the function, it merely sleeps for 1
millisecond. Looks like the problem is here:
 
   period = period < TICKS_PER_MILLI ? 
     1 : // <------------------------------------------------- BUG?
     period / TICKS_PER_MILLI;
 
 Should it be testing if period is greater than MAX_SLEEP_MILLS, rather than
less than TICKS_PER_MILLI?
This test was meant to make the min sleep time 1 millisecond, but I think I'm going to remove it.
 Should I file a bug report?
Don't bother. But thanks for the report. Sean
Nov 01 2008
next sibling parent reply John C <johnch_atms hotmail.com> writes:
Sean Kelly Wrote:

 Should I file a bug report?
Don't bother. But thanks for the report. Sean
Also, any reason why priority is only available once the Thread's handle has been created - ie, after it's been started?
Nov 01 2008
parent Sean Kelly <sean invisibleduck.org> writes:
John C wrote:
 Sean Kelly Wrote:
 
 Should I file a bug report?
Don't bother. But thanks for the report.
Also, any reason why priority is only available once the Thread's handle has been created - ie, after it's been started?
Do you mean as opposed to in its ctor? Sean
Nov 01 2008
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Sean Kelly wrote:
 John C wrote:
 I think Thread.sleep, which was introduced in core.thread in 2.020, is 
 broken on Win32. No matter what value I pass to the function, it 
 merely sleeps for 1 millisecond. Looks like the problem is here:

   period = period < TICKS_PER_MILLI ?     1 : // 
 <------------------------------------------------- BUG?
     period / TICKS_PER_MILLI;

 Should it be testing if period is greater than MAX_SLEEP_MILLS, rather 
 than less than TICKS_PER_MILLI?
This test was meant to make the min sleep time 1 millisecond, but I think I'm going to remove it.
Oh, I should mention that Thread.sleep() actually works correctly, even with this check in place. The sleep parameter uses a 100ns resolution, so to sleep for one millisecond you must use 10_000, while to sleep for one second it's 10_000_000. This isn't the same as Windows, which uses a millisecond resolution. I've tested this routine on Windows, however, and have verified that it works correctly. The docs are wrong however, as they say 500 = one millisecond. I'll fix that. Sean
Nov 01 2008
parent reply John C <johnch_atms hotmail.com> writes:
Sean Kelly Wrote:

 Sean Kelly wrote:
 John C wrote:
 I think Thread.sleep, which was introduced in core.thread in 2.020, is 
 broken on Win32. No matter what value I pass to the function, it 
 merely sleeps for 1 millisecond. Looks like the problem is here:

   period = period < TICKS_PER_MILLI ?     1 : // 
 <------------------------------------------------- BUG?
     period / TICKS_PER_MILLI;

 Should it be testing if period is greater than MAX_SLEEP_MILLS, rather 
 than less than TICKS_PER_MILLI?
This test was meant to make the min sleep time 1 millisecond, but I think I'm going to remove it.
Oh, I should mention that Thread.sleep() actually works correctly, even with this check in place. The sleep parameter uses a 100ns resolution, so to sleep for one millisecond you must use 10_000, while to sleep for one second it's 10_000_000. This isn't the same as Windows, which uses a millisecond resolution. I've tested this routine on Windows, however, and have verified that it works correctly. The docs are wrong however, as they say 500 = one millisecond. I'll fix that. Sean
Now you tell me :-) Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is that right?
Nov 01 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
John C wrote:
 Sean Kelly Wrote:
 
 Sean Kelly wrote:
 John C wrote:
 I think Thread.sleep, which was introduced in core.thread in 2.020, is 
 broken on Win32. No matter what value I pass to the function, it 
 merely sleeps for 1 millisecond. Looks like the problem is here:

   period = period < TICKS_PER_MILLI ?     1 : // 
 <------------------------------------------------- BUG?
     period / TICKS_PER_MILLI;

 Should it be testing if period is greater than MAX_SLEEP_MILLS, rather 
 than less than TICKS_PER_MILLI?
This test was meant to make the min sleep time 1 millisecond, but I think I'm going to remove it.
Oh, I should mention that Thread.sleep() actually works correctly, even with this check in place. The sleep parameter uses a 100ns resolution, so to sleep for one millisecond you must use 10_000, while to sleep for one second it's 10_000_000. This isn't the same as Windows, which uses a millisecond resolution. I've tested this routine on Windows, however, and have verified that it works correctly. The docs are wrong however, as they say 500 = one millisecond. I'll fix that.
Now you tell me :-) Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes. Aean
Nov 01 2008
next sibling parent reply John C <johnch_atms hotmail.com> writes:
Sean Kelly Wrote:

 John C wrote:
 Sean Kelly Wrote:
 
 Sean Kelly wrote:
 John C wrote:
 I think Thread.sleep, which was introduced in core.thread in 2.020, is 
 broken on Win32. No matter what value I pass to the function, it 
 merely sleeps for 1 millisecond. Looks like the problem is here:

   period = period < TICKS_PER_MILLI ?     1 : // 
 <------------------------------------------------- BUG?
     period / TICKS_PER_MILLI;

 Should it be testing if period is greater than MAX_SLEEP_MILLS, rather 
 than less than TICKS_PER_MILLI?
This test was meant to make the min sleep time 1 millisecond, but I think I'm going to remove it.
Oh, I should mention that Thread.sleep() actually works correctly, even with this check in place. The sleep parameter uses a 100ns resolution, so to sleep for one millisecond you must use 10_000, while to sleep for one second it's 10_000_000. This isn't the same as Windows, which uses a millisecond resolution. I've tested this routine on Windows, however, and have verified that it works correctly. The docs are wrong however, as they say 500 = one millisecond. I'll fix that.
Now you tell me :-) Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes. Aean
That's why I wrote Mango's TimeSpan way back when...
Nov 01 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
John C wrote:
 Sean Kelly Wrote:
 
 John C wrote:
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes. Aean
That's why I wrote Mango's TimeSpan way back when...
Unfortunately, at the moment, that would mean putting TimeSpan into druntime (dcore?), which probably isn't going to happen. I hope that TimeSpan can make its way into a core part of Tango eventually. Socket, for instance, uses struct timeval directly -- if I recall correctly, client code has to construct timevals, and there's no constructor provided.
Nov 01 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Christopher Wright" wrote
 John C wrote:
 Sean Kelly Wrote:

 John C wrote:
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is 
 that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes. Aean
That's why I wrote Mango's TimeSpan way back when...
Unfortunately, at the moment, that would mean putting TimeSpan into druntime (dcore?), which probably isn't going to happen. I hope that TimeSpan can make its way into a core part of Tango eventually. Socket, for instance, uses struct timeval directly -- if I recall correctly, client code has to construct timevals, and there's no constructor provided.
Tango uses TimeSpan in most places (including Socket) except for core, which can't depend on other libs (TimeSpan resides in tango.time.Time). In places where TimeSpan cannot be used, or where it was deemed undesirable, a double representing seconds is used. My original intention for TimeSpan was for it to be in core for this reason, but I was overruled. If I had it my way, TimeSpan would be the only representation of time in Tango. -Steve
Nov 02 2008
parent Sean Kelly <sean invisibleduck.org> writes:
Steven Schveighoffer wrote:
 "Christopher Wright" wrote
 John C wrote:
 Sean Kelly Wrote:

 John C wrote:
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is 
 that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes. Aean
That's why I wrote Mango's TimeSpan way back when...
Unfortunately, at the moment, that would mean putting TimeSpan into druntime (dcore?), which probably isn't going to happen. I hope that TimeSpan can make its way into a core part of Tango eventually. Socket, for instance, uses struct timeval directly -- if I recall correctly, client code has to construct timevals, and there's no constructor provided.
Tango uses TimeSpan in most places (including Socket) except for core, which can't depend on other libs (TimeSpan resides in tango.time.Time). In places where TimeSpan cannot be used, or where it was deemed undesirable, a double representing seconds is used.
Walter pointed out to me that by using floating point in a runtime module that's always linked (ie. Thread), the floating point support code will be linked into every app as well. This is why I changed the sleep routine in druntime.
 My original intention for TimeSpan was for it to be in core for this reason, 
 but I was overruled.  If I had it my way, TimeSpan would be the only 
 representation of time in Tango.
Me too. It's silly that the core modules use a different representation for time than the other modules in Tango simply because the time structs were deemed too non-essential to place in the core. Sean
Nov 02 2008
prev sibling parent reply torhu <no spam.invalid> writes:
Sean Kelly wrote:
 John C wrote:
...
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes.
I assume people won't need a higher resolution than milliseconds that often. Could Thread.sleep be changed into something like this? Thread.sleep(long millis, long hundredsOfNanos=0);
Nov 02 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
torhu wrote:
 Sean Kelly wrote:
 John C wrote:
...
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is 
 that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes.
I assume people won't need a higher resolution than milliseconds that often. Could Thread.sleep be changed into something like this? Thread.sleep(long millis, long hundredsOfNanos=0);
While Windows uses milliseconds, *nix uses either micrososeconds (usleep) or a combination of seconds and nanoseconds (nanosleep), so while using milliseconds may be more natural for Windows users it's liable to confuse others. I suppose what I'm getting at is that there's no resolution that's natural for everyone, and accepting a raw integer as a timespan is going to cause problems no matter what resolution is chosen--it's just too easy to get the number of zeros wrong. So I'd rather aim for establishing a structured form of time representation than to try and tweak the current setup. In the interim, Tango users will be happy to note that Thread.sleep() uses the same resolution as TimeSpan uses internally, so calling this routine from Tango using a TimeSpan should be pretty straightforward. Sean
Nov 02 2008
parent John C <johnch_atms hotmail.com> writes:
Sean Kelly Wrote:

 torhu wrote:
 Sean Kelly wrote:
 John C wrote:
...
 Win32's Sleep(50) seems to be the same as Thread.sleep(500_000). Is 
 that right?
Yup. There should probably be some sort of TimeSpan struct to help prevent these mistakes.
I assume people won't need a higher resolution than milliseconds that often. Could Thread.sleep be changed into something like this? Thread.sleep(long millis, long hundredsOfNanos=0);
While Windows uses milliseconds, *nix uses either micrososeconds (usleep) or a combination of seconds and nanoseconds (nanosleep), so while using milliseconds may be more natural for Windows users it's liable to confuse others. I suppose what I'm getting at is that there's no resolution that's natural for everyone, and accepting a raw integer as a timespan is going to cause problems no matter what resolution is chosen--it's just too easy to get the number of zeros wrong. So I'd rather aim for establishing a structured form of time representation than to try and tweak the current setup. In the interim, Tango users will be happy to note that Thread.sleep() uses the same resolution as TimeSpan uses internally, so calling this routine from Tango using a TimeSpan should be pretty straightforward. Sean
It is: import tango.time.Time, core.thread; Thread.sleep(TimeSpan.fromMillis(50).ticks);
Nov 02 2008
prev sibling parent reply John C <johnch_atms hotmail.com> writes:
Sean Kelly Wrote:

 John C wrote:
 Sean Kelly Wrote:
 
 Should I file a bug report?
Don't bother. But thanks for the report.
Also, any reason why priority is only available once the Thread's handle has been created - ie, after it's been started?
Do you mean as opposed to in its ctor? Sean
Not really - I mean that you should be able to set a Thread object's priority after creation but before start() is called. Currently this doesn't work - an exception is thrown. Perhaps store the requested priority in a field in the class, and SetPriority with that value on the handle after _beginthreadex?
Nov 01 2008
parent Sean Kelly <sean invisibleduck.org> writes:
John C wrote:
 Sean Kelly Wrote:
 
 John C wrote:
 Sean Kelly Wrote:

 Should I file a bug report?
Don't bother. But thanks for the report.
Also, any reason why priority is only available once the Thread's handle has been created - ie, after it's been started?
Do you mean as opposed to in its ctor?
Not really - I mean that you should be able to set a Thread object's priority after creation but before start() is called. Currently this doesn't work - an exception is thrown. Perhaps store the requested priority in a field in the class, and SetPriority with that value on the handle after _beginthreadex?
Thread.start() mostly exists to ensure that classes derived from Thread are properly constructed before the thread is started, so I don't encourage constructing threads and then letting them sit before starting them. For this reason, there is basically no support built into Thread for this "initialized but not started" state. There's an isRunning method but no state method that has an INIT state, for example. So while it would be possible to store thread priority info until the thread is started, this would really only support an approach that I don't really encourage anyway. I could probably be convinced to change it, but I'm not inclined to right now :) Sean
Nov 01 2008