X-Git-Url: http://nitlanguage.org diff --git a/lib/realtime.nit b/lib/realtime.nit index 6e312ef..33708b6 100644 --- a/lib/realtime.nit +++ b/lib/realtime.nit @@ -23,7 +23,7 @@ in "C header" `{ in "C" `{ -#ifdef __MACH__ +#if defined(__MACH__) && !defined(CLOCK_REALTIME) /* OS X does not have clock_gettime, mascarade it and use clock_get_time * cf http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx */ @@ -44,7 +44,7 @@ void clock_gettime(clock_t clock_name, struct timespec *ts) { `} # Elapsed time representation. -extern class Timespec `{struct timespec*`} +private extern class Timespec `{struct timespec*`} # Init a new Timespec from `s` seconds and `ns` nanoseconds. new ( s, ns : Int ) `{ @@ -74,16 +74,29 @@ extern class Timespec `{struct timespec*`} `} # Subtract `other` from `self` - fun -(other: Timespec): Timespec - do - var s = sec - other.sec - var ns = nanosec - other.nanosec - if ns < 0 then - s -= 1 - ns += 1000000000 - end - return new Timespec(s, ns) - end + fun -(other: Timespec): Timespec `{ + time_t s = self->tv_sec - other->tv_sec; + long ns = self->tv_nsec - other->tv_nsec; + if (ns < 0) { + s -= 1; + ns += 1000000000l; + } + struct timespec* tv = malloc(sizeof(struct timespec)); + tv->tv_sec = s; tv->tv_nsec = ns; + return tv; + `} + + # Set `self` to `a` - `b` + fun minus(a, b: Timespec) `{ + time_t s = a->tv_sec - b->tv_sec; + long ns = a->tv_nsec - b->tv_nsec; + if (ns < 0) { + s -= 1; + ns += 1000000000l; + } + self->tv_sec = s; + self->tv_nsec = ns; + `} # Number of whole seconds of elapsed time. fun sec : Int `{ @@ -114,26 +127,45 @@ extern class Timespec `{struct timespec*`} # Number of seconds as a `Float` # # Incurs a loss of precision, but the result is pretty to print. - fun to_f: Float do return sec.to_f + nanosec.to_f / 1000000000.0 + fun to_f: Float `{ + return (double)self->tv_sec + 0.000000001 * self->tv_nsec; + `} redef fun to_s do return "{to_f}s" end # Keeps track of real time +# +# ~~~ +# var clock = new Clock +# +# # sleeping at least 1s +# 1.0.sleep +# assert clock.total >= 1.0 +# assert clock.lapse >= 1.0 +# +# # sleeping at least 5ms +# 0.005.sleep +# assert clock.total >= 1.005 +# assert clock.lapse >= 0.005 +# ~~~ class Clock + super FinalizableOnce # TODO use less mallocs # Time at creation - protected var time_at_beginning = new Timespec.monotonic_now + private var time_at_beginning = new Timespec.monotonic_now # Time at last time a lapse method was called - protected var time_at_last_lapse = new Timespec.monotonic_now + private var time_at_last_lapse = new Timespec.monotonic_now + + private var temp = new Timespec.monotonic_now # Smallest time frame reported by clock - fun resolution: Timespec `{ + private fun resolution: Timespec `{ struct timespec* tv = malloc( sizeof(struct timespec) ); -#ifdef __MACH__ +#if defined(__MACH__) && !defined(CLOCK_REALTIME) clock_serv_t cclock; int nsecs; mach_msg_type_number_t count; @@ -151,34 +183,40 @@ class Clock # Seconds since the creation of this instance fun total: Float do - var now = new Timespec.monotonic_now - var diff = now - time_at_beginning - var r = diff.to_f - diff.free - now.free - return r + var now = temp + now.update + now.minus(now, time_at_beginning) + return now.to_f end # Seconds since the last call to `lapse` fun lapse: Float do - var nt = new Timespec.monotonic_now - var dt = nt - time_at_last_lapse - var r = dt.to_f - dt.free - time_at_last_lapse.free - time_at_last_lapse = nt + var time_at_last_lapse = time_at_last_lapse + var now = temp + now.update + time_at_last_lapse.minus(now, time_at_last_lapse) + var r = time_at_last_lapse.to_f + + self.temp = time_at_last_lapse + self.time_at_last_lapse = now + return r end # Seconds since the last call to `lapse`, without resetting the lapse counter fun peek_lapse: Float do - var nt = new Timespec.monotonic_now - var dt = nt - time_at_last_lapse - var r = dt.to_f - nt.free - dt.free - return r + var now = temp + now.update + now.minus(now, time_at_last_lapse) + return now.to_f + end + + redef fun finalize_once + do + time_at_beginning.free + time_at_last_lapse.free + temp.free end end