X-Git-Url: http://nitlanguage.org diff --git a/lib/realtime.nit b/lib/realtime.nit index b66ade0..39c5a27 100644 --- a/lib/realtime.nit +++ b/lib/realtime.nit @@ -10,8 +10,8 @@ # You are allowed to redistribute it and sell it, alone or is a part of # another product. -# Provides the Clock utility class to keep time of real time flow -module realtime is c_linker_option("-lrt") +# Services to keep time of the wall clock time +module realtime is ldflags "-lrt" in "C header" `{ #ifdef _POSIX_C_SOURCE @@ -21,6 +21,28 @@ in "C header" `{ #include `} +in "C" `{ + +#ifdef __MACH__ +/* OS X does not have clock_gettime, mascarade it and use clock_get_time + * cf http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx +*/ +#include +#include +#define CLOCK_REALTIME CALENDAR_CLOCK +#define CLOCK_MONOTONIC SYSTEM_CLOCK +void clock_gettime(clock_t clock_name, struct timespec *ts) { + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), clock_name, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; +} +#endif +`} + # Elapsed time representation. extern class Timespec `{struct timespec*`} @@ -48,32 +70,50 @@ extern class Timespec `{struct timespec*`} # Update `self` clock. fun update `{ - clock_gettime( CLOCK_MONOTONIC, recv ); + clock_gettime(CLOCK_MONOTONIC, self); `} - # Substract a Timespec from `self`. - fun - ( o : Timespec ) : Timespec + # Subtract `other` from `self` + fun -(other: Timespec): Timespec do - var s = sec - o.sec - var ns = nanosec - o.nanosec - if ns > nanosec then s += 1 - return new Timespec( s, ns ) + 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 # Number of whole seconds of elapsed time. fun sec : Int `{ - return recv->tv_sec; + return self->tv_sec; `} # Rest of the elapsed time (a fraction of a second). # # Number of nanoseconds. fun nanosec : Int `{ - return recv->tv_nsec; + return self->tv_nsec; + `} + + # Elapsed time in microseconds, with both whole seconds and the rest + # + # May cause an `Int` overflow, use only with a low number of seconds. + fun microsec: Int `{ + return self->tv_sec*1000000 + self->tv_nsec/1000; + `} + + # Elapsed time in milliseconds, with both whole seconds and the rest + # + # May cause an `Int` overflow, use only with a low number of seconds. + fun millisec: Int `{ + return self->tv_sec*1000 + self->tv_nsec/1000000; `} - # Seconds in Float - # Loss of precision but great to print + # 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 redef fun to_s do return "{to_f}s" @@ -90,7 +130,18 @@ class Clock # Smallest time frame reported by clock fun resolution : Timespec `{ struct timespec* tv = malloc( sizeof(struct timespec) ); +#ifdef __MACH__ + clock_serv_t cclock; + int nsecs; + mach_msg_type_number_t count; + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_attributes(cclock, CLOCK_GET_TIME_RES, (clock_attr_t)&nsecs, &count); + mach_port_deallocate(mach_task_self(), cclock); + tv->tv_sec = 0; + tv->tv_nsec = nsecs; +#else clock_getres( CLOCK_MONOTONIC, tv ); +#endif return tv; `} @@ -108,4 +159,15 @@ class Clock time_at_last_lapse = nt return dt 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 + end end