[D-runtime] druntime commit, revision 410

Jonathan M Davis jmdavisProg at gmx.com
Fri Nov 5 13:51:29 PDT 2010


On Friday, November 05, 2010 13:09:39 Sean Kelly wrote:
> On Nov 5, 2010, at 11:43 AM, Fawzi Mohamed wrote:
> > On 5-nov-10, at 18:59, Sean Kelly wrote:
> >> On Nov 5, 2010, at 9:12 AM, Fawzi Mohamed wrote:
> >>> Using integers one has to somehow give access to the time unit in some
> >>> way, and so make the interface more complex. If different timers have
> >>> different resolution different structures have to be used. Thus they
> >>> lead to a more complex interface.
> >> 
> >> I disagree.  With the Duration code, the call looks like this:
> >>   Thread.sleep(seconds(5) + milliseconds(10))
> >> 
> >> How is that complex?  Though I'll admit that the double version is pretty 
straightforward too:
> > You are right, It is not complex if you use it only for that.
> > But if later you want to use the same/similar structure for different
> > clocks (probably outside the core), then you have problems if the other
> > clock has a different resolution.
> 
> Resolution is only relevant insofar as the maximum and minimum duration
> that can be represented.  Using a signed 64-bit value at a nanosecond
> resolution, the maximum duration that can be represented is roughly 300
> years, and bumping the resolution to 100ns increments (as in C#) would
> make this 30,000 years.  Is there really a need for multiple-resolution
> durations?  Perhaps duration should use a double internally as well?  One
> of my concerns of using std.datetime as-is is that I'd need 4 overloads of
> Thread.sleep(), one for each duration type.  This suggests to me that
> durations in std.datetime really weren't intended for independent use.

The idea with the different durations that were in std.datetime was that you'd do 
calls like Dur.years(1) + Dur.days(2) and have exactly the correct duration 
types without worrying about what they actually were. The Dur functions returned 
the correct duration type for that unit, and any arithmetic done on them 
resulted in the correct duration type. So, for the most part, you didn't have to 
worry about the duration types. However, any function that took a duration would 
typically have been templated on the duration type. In the case of sleep, it 
would only have been able to take an HNSecDuration or TickDuration anyway, since 
MonthDuration and JointDuration wouldn't have been convertable without a specific 
date (hence why they existed in the first place rather than just having 
HNSecDuration for normal duration stuff and TickDuration for the few things that 
actually cared about clock ticks).

The problem, of course, was that anyone looking at the situation saw multiple 
duration types and was wondering why and what they were for and how to use them, 
even though the use case was really simple, and you really didn't have to worry 
about the types for the most part (passing durations to functions that you wrote 
was nearly the only place that it would have mattered). So, there was a fair bit 
of confusion there. It's a bit like how many of the return types in 
std.algorithm tend to scare people when liberal use of auto (and possible 
std.array.array) solves the problem quite easily, and you don't have to worry 
about them. So, I liked them, but it seemed like the confusion caused was too 
great to keep them. years and months now get dealt with separately from 
durations.

When I was designing them, I certainly wasn't thinking about using them with 
stuff in core like Thread.sleep() and the like, but I'm not sure that I would 
have done anything differently if I had. I'd have just made Thread.sleep() take 
an HNSecDuration, since MonthDuration and JointDuration would have made no sense 
in that context, and you could always cast TickDuration to an HNSecDuration if 
you really wanted to use a TickDuration for some reason (though I think that 
about the only place that a typical programmer would use TickDuration directly 
would be when using StopWatch). So, that's essentially, what I'm going to 
propose now, except that it's Duration instead of HNSecDuration (it was renamed 
on the demise of MonthDuration and JointDuration). Thread.sleep() and its 
friends can take a Duration, and if someone really wants to use a TickDuration, 
they can cast it.

Now, Duration has 100 ns precision, so if you really want a sleep function that 
goes to nanosecond resolution, then you'd have to have it also take a 
TickDuration - if a clock tick is a high enough resolution, TickDuration could 
be used to get something as precise as nanoseconds - but while it can 
theoretically hold nanoseconds, it can't actually return them or be assigned 
them without doing the calculations yourself (hnsecs is the highest resolution 
that it supports directly, but it holds its length in clock ticks). But since 
Linux doesn't seem to support a resolution higher than microseconds (on any 
system I've used anyway), and while Windows does support a higher resolution, 
it's not much higher than microseconds IIRC, I'm not sure if there's much point 
in trying to support resolutions higher than hnsecs.

- Jonathan M Davis


More information about the D-runtime mailing list