[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