in "C" `{
-#if defined(__MACH__) && !defined(CLOCK_REALTIME)
+#ifdef __APPLE__
+ #include <TargetConditionals.h>
+ #if defined(TARGET_OS_IPHONE) && __IPHONE_OS_VERSION_MIN_REQUIRED < 100000
+ // Preserve compatibility with pre-iOS 10 devices where there is no clock_get_time.
+ #undef CLOCK_REALTIME
+ #endif
+#endif
+
+#if (defined(__MACH__) || defined(TARGET_OS_IPHONE)) && !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
*/
#include <mach/clock.h>
#include <mach/mach.h>
+#undef CLOCK_REALTIME
+#undef CLOCK_MONOTONIC
#define CLOCK_REALTIME CALENDAR_CLOCK
#define CLOCK_MONOTONIC SYSTEM_CLOCK
-void clock_gettime(clock_t clock_name, struct timespec *ts) {
+void nit_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);
ts->tv_sec = mts.tv_sec;
ts->tv_nsec = mts.tv_nsec;
}
+#else
+ #define nit_clock_gettime clock_gettime
#endif
`}
# 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 ) `{
# Init a new Timespec from now.
new monotonic_now `{
struct timespec* tv = malloc( sizeof(struct timespec) );
- clock_gettime( CLOCK_MONOTONIC, tv );
+ nit_clock_gettime( CLOCK_MONOTONIC, tv );
return tv;
`}
# Update `self` clock.
fun update `{
- clock_gettime(CLOCK_MONOTONIC, self);
+ nit_clock_gettime(CLOCK_MONOTONIC, self);
`}
# 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 `{
# 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
# 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) );
-#if defined(__MACH__) && !defined(CLOCK_REALTIME)
+#if (defined(__MACH__) || defined(TARGET_OS_IPHONE)) && !defined(CLOCK_REALTIME)
clock_serv_t cclock;
int nsecs;
mach_msg_type_number_t count;
# 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