
On Nov 18, 2008, at 5:28 PM, Beman Dawes wrote:
On Tue, Nov 18, 2008 at 7:56 PM, Howard Hinnant <hinnant@twcny.rr.com> wrote:
It seems a shame that process_clock does not really meet the proposed standard clock requirements (its now() doesn't return the time_point). That being said, I can see why you didn't. This clock really has 3 distinct "time points" and one needs to set each of those three with one system call.
Yep, and I couldn't see any practical downside to the proposed now() signature. Other than that, I did try to make process_clock conform.
If one wanted, one could easily create a user_time_clock wrapper around processor_clock to adapt it to the standard clock requirements if needed.
Yes. Interesting. That hadn't occurred to me.
Just for general education purposes, here's a portable processor- time clock (just to show how easy it is to build a custom clock):
#include <ctime> #include <cstdio> #include <chrono>
class processor_clock { public: typedef std::clock_t rep; typedef std::ratio<1, CLOCKS_PER_SEC> period; typedef std::chrono::duration<rep, period> duration; typedef std::chrono::time_point<processor_clock> time_point; static const bool is_monotonic = true;
static time_point now() {return time_point(duration(std::clock()));} };
int main() { processor_clock::time_point t1 = processor_clock::now(); processor_clock::time_point t2 = processor_clock::now(); std::printf("%g seconds\n", std::chrono::duration<double>(t2-t1).count()); }
Output:
4e-06 seconds
I'll add that to the docs. The clock requirements are really nice; they are totally minimalist, yet provide all the functionality needed.
Did you look at the boost/chrono/timer.hpp header? It supplies a timer template to create a timer from any clock. I'd be curious to get your reactionsl
You caught me napping. :-) It looks like a nice utility. Comments: * It looks like you would like to see a standard overload of now: static time_point now(); // might throw static time_point now(system::error_code& ec); // nothrow Please feel free to submit an issue on this. That being said, I just reviewed several POSIX time functions and it really looks like they just don't fail. I know the ones on darwin don't. I know the C standard (and POSIX) say things like:
The value (time_t)(-1)is returned if the calendar time is not available.
This strikes me as a situation where the function either never fails (it is supported), or always fails (it isn't supported). I'm not positive that the error_code overload is warranted for this situation. My preference would be that if the platform doesn't support system_clock (for example) that code using system_clock not compile instead of always fail at run time. Thus there would be no reason to check the error code (or expect an exception from now()). Currently the only thing [time] has to say on this subject is in [time.duration]/5:
Requires: Members of duration shall not throw exceptions other than those thrown by the indicated operations on their representations.
Perhaps we should widen that sentiment to time_point and clock::now(). * I've written utilities like this in the past. I've always put the functionality of elapsed() plus a print statement in ~timer() so that use cases looked like: int main() { timer _("Entire Program"); // do stuff } Output: Elapsed time for Entire Program was 15 seconds. I've had start(), and I think I probably renamed elapsed() to something like report() (due to the printing functionality), and I also had stop(). If report() was called prior to ~timer(), without another start(), then ~timer() did not report(). There was also a way to construct timer() without implicitly calling start(). Perhaps an elapsed() would have been a good addition to what I've done in the past. Wrist watch timer's I've seen have two versions of elapsed: 1. Get the elapsed time and keep the timer going. 2. Get the elapsed time and stop the timer. Maybe #1 could be handled by elapsed(), and #2 could be handled by having stop() return the elapsed time? There are disadvantages to the way I've done it (auto-report): One doesn't always want a print out, and if one does, one doesn't always want it to go to the same stream. For me this was always a debugging utility and thus such matters weren't that important. Since it did "auto-report", I really liked being able to distinguish among multiple timer outputs: void f1() { timer _("f1"); // ... } void f2() { timer _("f2"); // ... } int main() { timer _("main"); f1(); f2(); } Output: Elapsed time for f1 was 3 seconds. Elapsed time for f2 was 2 seconds. Elapsed time for main was 5 seconds. * I can't imagine ever using any clock but std::chrono::high_resolution_clock for timer. Even if high_resolution_clock isn't monotonic, I'm usually using this utility in a debug/test context and know better than to go resetting system clocks during a test. On OS X, high_resolution_clock will be monotonic (if I have anything to say about it). * Here's one way to get the total time spent in f1(), as opposed to the time per call: void f1() { static timer t("Total time spent in f1"); t.start(); // first start is redundant and ignored // ... t.stop(); } One might write a timer-wrapper which put the t.stop() in ~wrapper() (and took a timer& in its ctor and started it). void f1() { static timer t("Total time spent in f1"); timer_start_stop _(t); // ... } class timer_start_stop { timer& t_; public: explicit timer_start_stop(timer& t) : t_(t) {t_.start();} ~timer_start_stop() {t_.stop();} timer_start_stop(const timer_start_stop&) = delete; timer_start_stop& operator=(const timer_start_stop&) = delete; }; -Howard