Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Add ClockType enum to core.time for issue# 13433. #990

Merged
merged 2 commits into from
Apr 30, 2015

Conversation

jmdavis
Copy link
Member

@jmdavis jmdavis commented Oct 14, 2014

This adds an enum for indicating which type of clock to use when it's
appropriate for a time function to have multiple options for the source
clock. Currently, it only supports "normal" and "coarse," but we may add
more in the future, since some systems do support others (e.g
clock_gettime has several other options depending on the system).

This is in support of dlang/phobos#2584.

alias CLOCK_MONOTONIC_FAST coarseClock;
}
else
assert(0, "What is the COARSE monotonic clock for clock_gettime for this system?");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this jives with the description that:

If the function in question does not support the given clock (or it does on some systems but not the current system), then ClockType.normal is used.

I understand what you are trying to do, but I wonder if it should just be in a unit test instead of in the main code, so the developers are aware of it, but it doesn't impede adoption on a new platform.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schveiguy I think that the description and implementation jive just fine. The implementation is taking the normal approach of erroring out on new systems so that the developers there are forced to make the correct decision for that platform (either add the coarse clock if there is one or provide a branch of the implementation for that platform which doesn't use the coarse clock). From the user's perspective, the coarse clock may or may not work on the new system, but the developer is forced to deal with it.

The alternative is to just not provide a coarse clock on new platforms unless someone realizes on their own that it's an issue and implements it for that platform, and that's not normally how we deal with new platforms. In this case, it would likely mean that no new platforms would support the coarse clock even if they can and should.

As for just having unit tests, I don't see how that really tells the developers anything. At best, that means that if they're glancing through core.time and happen to see those tests and happen to wonder whether they need to do something for their specific platform and then look at the implementation and see that they do, I don't see how they're going to catch it. An explanatory comment would help with that, but they'd still have to be looking. It's common practice in druntime and Phobos to use static assertions for new platforms so that developers will know that they need to do something for that platform when it's added rather than assuming that everything is fine.

Now, I should probably rewrite this code a little so that the clock decision for clock_gettime is made in the version branches rather than in the call to clock_gettime so that it's easier to add a new POSIX platform with no coarse clock and so that other clocks can be added to specific platforms more easily later if we decide to do that, but I think that the basic approach here is fine and that it's in line with how we normally do things. The fact that the description says that the coarse clock is not necessarily supported doesn't really matter insofar as the developers have to figure out whether it's appropriate for the new system regardless, and without the assertion, they won't catch that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, I should probably rewrite this code a little so that the clock decision for clock_gettime is made in the version branches rather than in the call to clock_gettime

Yes, this will look better. Much better than my idea of using a unittest.

Just get rid of else version(posix) and the aliases to the coarseClock. It looks a bit messy currently, and this will make the code more consistent and readable. And as you said, clock options on other platforms will not affect Linux or FreeBSD.

What I was thinking about is, on a posix but not linux or freebsd platform, the default works, but the coarse clock just fails, and at runtime no less. This seems inconsistent to me. A much better situation would simply be to make the developer of the new platform figure it out during porting stage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see what you mean now. I intended for it to be a static assertion, but it's a regular assertion. It's supposed to fail at compile time. That's what we typically do with the else branch of a version block in druntime and Phobos. I just screwed up and forgot the static.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 15, 2014

Okay. I updated it so that the clock is chosen in the version branches, and I fixed it so that the assertion is static like it's supposed to be.

auto clockArg = type == ClockType.normal ? CLOCK_MONOTONIC : CLOCK_MONOTONIC_FAST;
}
else
static assert(0, "What is the COARSE monotonic clock for clock_gettime for this system?");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, 2 new comments :)

  1. I think the clockArg should be by default normal, not by default coarse. We don't know what "other" clocks would represent on other platforms. The way the code is now, it by default selects coarse. I'm wondering actually if it shouldn't be a final switch, so any new clocks added force the developer to handle those cases specifically.
  2. The static error message seems to focus only on COARSE, but it's possible all the clock defines may be differently named. I would change it to "Please handle all the clock types for this system."

@jmdavis
Copy link
Member Author

jmdavis commented Oct 17, 2014

Okay. I fixed it up again. Now it won't accidentally do coarse if a new clock type is added. I didn't use a final switch, because that would be a fair bit of extra code, and I don't think that it adds much value here. New platforms need the error from the static assertion so that the developers who are adding them know that they need to add the code for that platform, but anyone adding a new value to ClockType should already know that they need to look at currTime for core.time.MonoTime and std.datetime.Clock to see which platforms need to have it added rather than ignoring it and using ClockType.normal, or they wouldn't be doing anything with ClockType in the first place. So, erroring out on adding a new ClockType doesn't really add much, particularly when it would then have to be added to the final switch of each branch just so that it could be explicitly ignored.

assert(abs(coarse2 - norm1) <= seconds(1));
assert(abs(coarse1 - norm2) <= seconds(1));
assert(abs(coarse1 - norm1) <= seconds(1));
assert(abs(norm2 - norm1) <= seconds(1));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'm ready to say this is good to go, but I'm curious. I see some potential, very slight but still there, that these tests may fail, based on the usage of the system being tested on (which would be a false failure). Is there a good reason to have these tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What types of potential failures do you foresee? It's basically making sure that the values coming from the clocks are essentially the same. It would be very bad for instance if the coarse clock returned a completely different value than the the normal clock, because then when you compare the MonoTimes, you'd be comparing completely unrelated values. The coarse clock should just be updating less frequently and if the a coarse time and a normal time are close enough together, then it may look like the coarse one went backwards, but we don't want something like the coarse clock having 1000 and the normal one having 5000000 for approximately the same time - though maybe the solution to that is to add the clock type to MonoTime internally and throw an Error if MonoTimes with different clock types are compared... Then it would be possible to use totally different clocks for different MonoTimes without it being caught. It's possibilities for weirdness with that that made it so that I didn't add any ClockTypes for stuff like Linux's CLOCK_MONOTONIC_RAW or CLOCK_BOOTTIME, but if MonoTime has the clock type, that problem goes away. I'll have to consider that then.

Regardless, it looks like I missed the assert(coarse1 <= coarse2);, so I'll need to fix that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What types of potential failures do you foresee?

We are depending on a certain execution speed. It's far-fetched, but imagine that the process is put to sleep in between reading the two clocks, and some other process hangs the OS for over 1 second. Then when it comes back, the delta between the two reads is more than 1 second, you get a failure.

It would be very bad for instance if the coarse clock returned a completely different value than the the normal clock

I don't know if we need to guarantee this possibility. Although it may be the case today, we are not in control of the meaning of these two clocks, and this can possibly change (very unlikely), or on a new system (non- linux or freebsd), there are two possible clocks, one "quick", and one "slow" to retrieve, but they are not related to each other.

I think the only thing we need to guarantee is that fetching two times from the same clock source is sane. I'd almost recommend putting a sleep in between those calls, and dropping the = part of <=.

though maybe the solution to that is to add the clock type to MonoTime internally and throw an Error if MonoTimes with different clock types are compared...

I don't like that, this introduces another possible runtime check, and possibly another member to the struct.

Overall, I'm not vehemently opposed to the tests, I just was pointing out possible issues with them. In any case, unit testing time features is going to largely depend on the behavior of the OS, over which we have 0 control.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are depending on a certain execution speed. It's far-fetched, but imagine that the process is put to sleep in between reading the two clocks, and some other process hangs the OS for over 1 second. Then when it comes back, the delta between the two reads is more than 1 second, you get a failure.

Ah, true. That could definitely happen, but I'm loathe to use sleeps in general unless I have to, and I'm trying to specifically test that the clocks are very close to one another (just differing in precision, not units), so sleeps would actually defeat the purpose of the tests. So, I suspect that we're stuck the possibility of that random failure, though I think that it's unlikely - especially on the autotester where the boxes are dedicated to running the tests.

I really don't like the idea of MonoTime being able to be backed by two completely different clocks without any way to differentiate the resulting MonoTimes, because that could easily lead to weird behavior and nasty bugs if the clocks are mixed. I'm okay with using the coarse clock so long as it appears to just be grabbing the time less frequently at the kernel level and thus not be as up-to-date (which seems to be what's happening on both Linux and FreeBSD), but if they're completely different timers, then that's just begging for bugs IMHO to use MonoTime for both without a member variable differentiating them. So, that means either creating separate types for the different clocks or adding a member variable to differentiate them. Neither choice is particularly appealing, though between the two of them, I'd much prefer the member variable route. So, to avoid that, we need to ensure that the clocks being used have the same start time and units (or very close to it anyway, since we can't actually test for that directly). Without that, I think that we need to either add a member variable indicating the clock type or to not support the coarse clock (or any clock which does not have the same start time and units). Fortunately, it looks like the coarse clock is really just the same clock as the normal one except that it's grabbing the time from a place that isn't updated as frequently, so I think that we can support the coarse clock without having to worry about mixing clocks, but I think that it's then unlikely that any of the other clock types from the specific implementations of clock_gettime will be supported (except maybe CLOCK_MONOTIME_PRECISE on FreeBSD, but I haven't been able to find any info on what's different between that and the normal clock, which is supposed to be precise already).

I should probably better comment the tests though to make the intention clear.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because that could easily lead to weird behavior and nasty bugs if the clocks are mixed.

Well, from my understanding the "coarse" time is derived from the same clock as the monotonic time, but just captured once every tick by the OS instead of on demand. This means it's possible to read the monotonic time, and then read the coarse time, and get a negative delta. I think at the very least, we should warn people that we do not guarantee different clocks are exactly in sync.

Just a recommendation to only use one clock consistently would be good.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. That matches my understanding, and I agree that clocks shouldn't be mixed, but mixing the coarse and normal clocks should mostly work (particularly if you're dealing with values grabbed at least a millisecond or two apart), but other clocks would be a different story entirely, since their values wouldn't even necessarily mean the same thing. I'll add a note about not mixing clocks though.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 19, 2014

Okay. Updated.

@mleise
Copy link
Contributor

mleise commented Oct 19, 2014

Looks good to merge. Although in this state MonoTime locks out any systems which can provide a coarse clock through other means than just delaying the call to the precise clock. (MonoTime requires same base, same frequency and same wrap-around behavior, correct?) I'm just wondering because I don't know if GetTickCount on Windows >= XP SP2 is a candidate for a coarse, faster timer.
Clearly this would require an additional field, so yeah, let's keep it simple for now.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 19, 2014

MonoTime does not support wraparound, and no system that we support is in any danger of wrapping around (it would take centuries). But regardless, the coarse clock (and any other clock that we might support with MonoTime) must have the same units and start value as the normal clock, otherwise you're going to get MonoTimes with completely different internal values and no indication as to what clock they came from. We could add a member variable to MonoTime which indicates that and then throw an Error when different clock types are compared, but I'd like to avoid that unless we actually need it. Though thinking about that, I think that I need to adjust the documentation to make it clear that we might make comparing MonoTimes with different clock types throw an Error in the future, or we risk breaking code when someone assumes that it's okay to compares MonoTimes from the coarse and normal clocks.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 19, 2014

Okay. Documentation updated to note that it should be considered an error if MonoTimes from different clocks are compared and that it's possible that in the future such a comparison will throw an Error. That way, if we ever do make the decision to support different clock types and have to add such a field to MonoTime and throw on bad comparisons, people have been warned ahead of time that code which compared the coarse and normal clocks could start throwing Errors on them - though I suppose that we could exempt comparisons of the coarse and normal clocks on the theory that they're compatible enough to get away with it, and we definitely wouldn't break anyone's code that way. But that's a question for if/when we decide to worry about additional clocks (the documentation about a possible Error should give us some leeway though). As it is, this is the first time that supporting anything other than CLOCK_MONOTIME and CLOCK_REALTIME has ever come up.

@MartinNowak
Copy link
Member

Another option would be to use a separate type per clock domain, e.g. by templating MonoTime on ClockType.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 20, 2014

Another option would be to use a separate type per clock domain, e.g. by templating MonoTime on ClockType.

Hmm. Part of me thinks that that's a great idea, and part of me thinks that that's a horrible idea. It would definitely clean things up from the perspective of how handling potentially drastically different monotonic clocks would work, but it also introduces an extra level of complication in that MonoTime would then be templated. But since it would default to ClockType.normal, that might be okay. If we do that though, we might as well support some of the other monotonic clock types right of the bat, I suppose. It's definitely a flexible solution, but I also wonder if it's overengineering things a bit. Still, if we're ever going to support more clock types, it's probably a better way to go (whether we support them now or not), and it avoids ever having to add another member to MonoTime or having to worry about doing things like throwing Errors at runtime. Instead, we'd get complication errors, which is far safer.

I'll have to think about it, but it's a tempting solution.

MonoTime is really the only type that has to worry about this though, since it's so tied to the clock that it comes from. SysTime won't care no matter what extra clocks we might add (though AFAIK, it's really only the coarse clock - and maybe FreeBSD's CLOCK_REALTIME_PRECISE - that we'd have to think about adding for them, because it's in hnsecs since midnight, January 1st 1 A.D., and the clock that generated it is pretty much irrelevant.

@schveiguy
Copy link
Member

You can make MonoTime an alias specialization of the template (which should have a different name), so code doesn't break. Then anyone who really needs the other clock types can use it by instantiating directly.

You can always compare two unrelated times by comparing the hnsecs.

I'm for @MartinNowak's idea, if it helps.

@MartinNowak
Copy link
Member

It's definitely a flexible solution, but I also wonder if it's overengineering things a bit.

I was wondering whether adding more monotonic clock sources was overengineering, but apparently it's much faster to obtain a coarse clock than a finer one.

@MartinNowak
Copy link
Member

You can make MonoTime an alias specialization of the template (which should have a different name), so code doesn't break

Weird that you cannot use a templated MonoTime(ClockType c = ClockType.precise) with default arguments as MonoTime.
https://issues.dlang.org/show_bug.cgi?id=1012

@schveiguy
Copy link
Member

Weird that you cannot use a templated MonoTime(ClockType c = ClockType.precise) with default arguments as MonoTime.

I would still argue against that -- MonoTime is really named after the clock source -- monotonic clock. If we go with a templated solution, and you can't compare two different template instance types, then it would be nice to be able to use the same API for all clocks on the system that are available.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 20, 2014

I was wondering whether adding more monotonic clock sources was overengineering, but apparently it's much faster to obtain a coarse clock than a finer one.

It is faster, but it's precision is down to about a millisecond, which means that it's really only useful when you want to ask for the time very frequently but don't care about it being precise, which seems like a pretty weird use case to me.

Weird that you cannot use a templated MonoTime(ClockType c = ClockType.precise) with default arguments as MonoTime.

Ouch. If I new that, I'd forgotten about it. That sucks. LOL. We're basically forced to do what C++ does with std::string.

I would still argue against that -- MonoTime is really named after the clock source -- monotonic clock. If we go with a templated solution, and you can't compare two different template instance types, then it would be nice to be able to use the same API for all clocks on the system that are available.

Linux has something like 4 or 5 different clocks which are all monotonic, and MonoTime's API is designed specifically for monotonic clocks. I don't see much point in having it support other clocks (like CLOCK_REALTIME). If we go with templatizing MonoTime, we should probably just go with MonoTimeImpl for the struct name like Martin suggested in his post to the bug report. That matches what we've done in std.conv.to.

@schveiguy
Copy link
Member

Well, I like to keep options open :) I think that renaming it later probably will not be super-painful, but if we can find a name now that is generic enough not to be renamed later, that would be better. Most users will never even view this type, and avoid it completely, just using the vanilla MonoTime. As you said, the use cases are not plentiful, but there are very good ones. The fact that CLOCK_MONOTONIC_COARSE didn't even exist until a few years ago is a testament to that.

@MartinNowak
Copy link
Member

Most users will never even view this type, and avoid it completely, just using the vanilla MonoTime. As you said, the use cases are not plentiful, but there are very good ones.

Profiling with low overhead for example or request timings in a web app.

@jmdavis
Copy link
Member Author

jmdavis commented Oct 24, 2014

Okay. I just did a major rewrite. MonoTime is now an alias to MonoTimeImpl!(ClockType.normal), and I added values to ClockType for pretty much all of the stray clocks that Linux and FreeBSD support with clock_gettime. And on the theory that it really didn't make sense to treat stuff like MonoTimeImpl!(ClockType.uptime) as equivalent to MonoTimeImpl!(ClockType.normal) in most cases, it's no longer set up to treat unsupported clocks as equivalent to ClockType.normal. The exceptions are ClockType.coarse and ClockType.precise which MonoTimeImpl and Clock.currTime (which will now be templatized as well - in another PR - in order to validate the ClockType at compile time) will treat as equivalent to ClockType.normal. And ClockType.second (based on FreeBSD's CLOCK_SEC) will work with Clock.currTime (and only Clock.currTime) on all systems, since it should be easy enough to fake it on the others (it returns the time as fast as possible with no sub-second resolution - apparently FreeBSD has something in the kernel to make that really fast).

With MonoTimeImpl being templated, we might be able to use a different function on Windows or Mac OS X to get coarser time for the monotonic clock, but I don't feel like figuring those out right now, since I'm not very familiar with those APIs. So, for now, they'll just use the normal clock for the coarse one.

Maybe all of these clock types is taking it a bit far, but it is thorough enough that folks on Linux and FreeBSD shouldn't need to go to clock_gettime directly for any weird clocks, and by making sure that the design works with all of them, it should be trivial to add any new ones later.


$(LREF MonoTimeImpl) and $(D Clock.currTime) take the $(D ClockType) as a
template argument. In the case of $(LREF MonoTimeImpl), the alias
$(LREF MonoTime) (which is $(D MonoTimeImpl!(Clock.currTime))) is provided
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MonoTimeImpl!(ClockType.normal)

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Okay. I merged in Steven's fix and rebased so that we wouldn't have a slew of commits for this. Hopefully, it finally passes the autotester this time.

@schveiguy
Copy link
Member

We're having initialization order issues with MonoTime in the GC anyhow

See #1238

@schveiguy
Copy link
Member

Nuts. It fails on FreeBSD. I can't see why it would... If it's failing on Linux too, I'll look at see if there's something I messed up.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Nuts. It fails on FreeBSD. I can't see why it would... If it's failing on Linux too, I'll look at see if there's something I messed up.

I thought that I'd tested it locally. I guess not. And I might have screwed something up when I merged it, since I did make a few minor tweaks (e.g. change some of the _ticksPerSecond[_clockIdx] to ticksPerSecond, since ticksPerSecond and _ticksPerSecond hadn't been used particularly consistently).

if(_ticksPerSecond == 0)
assert(0, "MonoTime failed to get the frequency of the system's monotonic clock.");
if(ticksPerSecond == 0)
assert(0, "MonoTimMonoTimeImpl failed to get the frequency of the system's monotonic clock.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... MonoTimMonoTimeImpl? :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably use that nifty new _clockIdx to get the name of the clock for this message :)

@schveiguy
Copy link
Member

Hah, It could be another wonderful FreeBSD bug :) I'll deprecate the test just in case.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Hah, It could be another wonderful FreeBSD bug :) I'll deprecate the test just in case.

It looks like an invalid ClockType is being used for somehow.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

It looks like an invalid ClockType is being used for somehow.

No, that's not it. I mixed up clockArg an clockType when debugging.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

No. I think that the problem is clockArg in the static constructor. clockArg is set at the beginning of MonoTimeImpl with one of the C constants. It's not the same as the value of ClockType, which is simply an enum. And in the static constructor, clockArg is set with the value of ClockType. Annoyingly enough, the pile of code which defines clockArg in MonoTimeImpl will have to be copied... :(

@schveiguy
Copy link
Member

No need to do that I think, just change to this:

mixin("auto clockArg = ClockType." ~ typeStr ~ ";");

@schveiguy
Copy link
Member

I'm surprised if the original doesn't work though, I thought alias would be OK within each scope, but maybe it has weird interactions with static foreach.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

No need to do that I think, just change to this:
mixin("auto clockArg = ClockType." ~ typeStr ~ ";");

No. That's wrong. The value of ClockType has nothing to do with the value of clockArg. ClockType is an enum with the same values for each of its enum values across all systems, whereas clockArg is the value of the corresponding constant from the C API (e.g. CLOCK_MONOTONIC or CLOCK_MONOTONIC_COARSE) which varies from system to system and don't necessarily increment linearly.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Okay. That's been fixed, and I fancied up some of the assert messages to use the name of the ClockType value being used (as well as fixing that horrible typo). Hopefully, it all passes the autotester this time.

@schveiguy
Copy link
Member

No. That's wrong. The value of ClockType has nothing to do with the value of clockArg.

Huh? That's the argument you are passing to clock_getres. Since I'm not instantiating the template any more, there's no need to have the actual alias.

Edit: totally understand now. Sorry.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Huh? That's the argument you are passing to clock_getres. Since I'm not instantiating the template any more, there's no need to have the actual alias.

Yes. It's the value that's being passed to clock_getres - which is what's being used to get the value for _ticksPerSecond. ClockType is not the value that gets passed to clock_gettres. clockArg is. ClockType is used to determine what clockArg should be set to, but the actual value of ClockType is not what's passed to clock_getres and has no relation to it other than its name. You were passing the values of ClockType to clock_getres, so of course, clock_getres failed, resulting in _ticksPerSecond not being set.

@jmdavis
Copy link
Member Author

jmdavis commented Apr 29, 2015

Edit: totally understand now. Sorry.

It happens.

mixin("static if(clockType == ClockType." ~ val ~ `) return "enum name = \"` ~ val ~ `\";";`);
assert(0);
}
mixin(genMix());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually now replace all this with:

enum name = __traits(allMembers, ClockType)[_clockIdx];

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Good point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

This adds an enum for indicating which type of clock to use when it's
appropriate for a time function to have multiple options for the source
clock. In the case of MonoTime, to make that work cleanly, the
implementation of MonoTime has become MonoTimeImpl, templated on
ClockType, and MonoTime has become an alias to
MonoTimeImpl!(ClockType.normal). In the case of SysTime (in a separate
PR), that will a default template argument to Clock.currTime and SysTime
will be unaffected (because in MonoTime's case, the clock that it came
from is integral to the type, whereas in SysTime's case, it doesn't
matter after the SysTime has been initialized).
@schveiguy
Copy link
Member

Hot damn! it passes :) I'm good with merging this, I'll let others review since it's changed a bunch today.

@MartinNowak
Copy link
Member

Auto-merge toggled on

MartinNowak added a commit that referenced this pull request Apr 30, 2015
Add ClockType enum to core.time for issue# 13433.
@MartinNowak MartinNowak merged commit bcfc36b into dlang:master Apr 30, 2015
@jmdavis jmdavis deleted the 13433 branch May 1, 2015 08:03
else static if(clockType == ClockType.processCPUTime) alias clockArg = CLOCK_PROCESS_CPUTIME_ID;
else static if(clockType == ClockType.raw) alias clockArg = CLOCK_MONOTONIC_RAW;
else static if(clockType == ClockType.threadCPUTime) alias clockArg = CLOCK_THREAD_CPUTIME_ID;
else static assert(0, "ClockType." ~ typeStr ~ " is not supported by MonoTimeImpl on this system.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the documentation build because with version (CoreDdoc) the enum contains all members.
I'd suggest to initialize the clock resolutions lazily instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MartinNowak
Copy link
Member

Interesting benchmark numbers to get the time with different clocks.
PEP 0418 -- Add monotonic time, performance counter, and process time functions | Python.org

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
6 participants