X-Git-Url: http://nitlanguage.org diff --git a/lib/realtime.nit b/lib/realtime.nit index 72a9d5f..ad64930 100644 --- a/lib/realtime.nit +++ b/lib/realtime.nit @@ -11,7 +11,7 @@ # another product. # Provides the Clock utility class to keep time of real time flow -module realtime is c_linker_option("-lrt") +module realtime is ldflags "-lrt" in "C header" `{ #ifdef _POSIX_C_SOURCE @@ -21,17 +21,46 @@ 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*`} + + # Init a new Timespec from `s` seconds and `ns` nanoseconds. new ( s, ns : Int ) `{ struct timespec* tv = malloc( sizeof(struct timespec) ); tv->tv_sec = s; tv->tv_nsec = ns; return tv; `} + + # Init a new Timespec from now. new monotonic_now `{ struct timespec* tv = malloc( sizeof(struct timespec) ); clock_gettime( CLOCK_MONOTONIC, tv ); return tv; `} + + # Init a new Timespec copied from another. new copy_of( other : Timespec ) `{ struct timespec* tv = malloc( sizeof(struct timespec) ); tv->tv_sec = other->tv_sec; @@ -39,9 +68,12 @@ extern class Timespec `{struct timespec*`} return tv; `} + # Update `self` clock. fun update `{ - clock_gettime( CLOCK_MONOTONIC, recv ); + clock_gettime(CLOCK_MONOTONIC, self); `} + + # Substract a Timespec from `self`. fun - ( o : Timespec ) : Timespec do var s = sec - o.sec @@ -50,15 +82,35 @@ extern class Timespec `{struct timespec*`} 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; `} - # Seconds in Float - # Loss of precision but great to print + # 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; + `} + + # 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" @@ -75,7 +127,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; `}