1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Alexis Laferrière <alexis.laf@xymus.net>
5 # This file is free software, which comes along with NIT. This software is
6 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 # is kept unaltered, and a notification of the changes is added.
10 # You are allowed to redistribute it and sell it, alone or is a part of
13 # Services to keep time of the wall clock time
14 module realtime
is ldflags
"-lrt"
17 #ifdef _POSIX_C_SOURCE
18 #undef _POSIX_C_SOURCE
20 #define _POSIX_C_SOURCE 199309L
26 #if defined(__MACH__) && !defined(CLOCK_REALTIME)
27 /* OS X does not have clock_gettime, mascarade it and use clock_get_time
28 * cf http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx
30 #include <mach/clock.h>
31 #include <mach/mach.h>
32 #define CLOCK_REALTIME CALENDAR_CLOCK
33 #define CLOCK_MONOTONIC SYSTEM_CLOCK
34 void clock_gettime(clock_t clock_name, struct timespec *ts) {
37 host_get_clock_service(mach_host_self(), clock_name, &cclock);
38 clock_get_time(cclock, &mts);
39 mach_port_deallocate(mach_task_self(), cclock);
40 ts->tv_sec = mts.tv_sec;
41 ts->tv_nsec = mts.tv_nsec;
46 # Elapsed time representation.
47 private extern class Timespec `{struct timespec*`}
49 # Init a new Timespec from `s
` seconds and `ns
` nanoseconds.
50 new ( s, ns : Int ) `{
51 struct timespec
* tv
= malloc
( sizeof
(struct timespec
) );
52 tv-
>tv_sec
= s
; tv-
>tv_nsec
= ns
;
56 # Init a new Timespec from now.
58 struct timespec
* tv
= malloc
( sizeof
(struct timespec
) );
59 clock_gettime
( CLOCK_MONOTONIC, tv
);
63 # Init a new Timespec copied from another.
64 new copy_of( other : Timespec ) `{
65 struct timespec
* tv
= malloc
( sizeof
(struct timespec
) );
66 tv-
>tv_sec
= other-
>tv_sec
;
67 tv-
>tv_nsec
= other-
>tv_nsec
;
71 # Update `self` clock.
73 clock_gettime
(CLOCK_MONOTONIC, self);
76 # Subtract `other
` from `self`
77 fun -(other: Timespec): Timespec `{
78 time_t s
= self-
>tv_sec
- other-
>tv_sec
;
79 long ns
= self-
>tv_nsec
- other-
>tv_nsec
;
84 struct timespec
* tv
= malloc
(sizeof
(struct timespec
));
85 tv-
>tv_sec
= s
; tv-
>tv_nsec
= ns
;
89 # Set `self` to `a
` - `b
`
90 fun minus(a, b: Timespec) `{
91 time_t s
= a-
>tv_sec
- b-
>tv_sec
;
92 long ns
= a-
>tv_nsec
- b-
>tv_nsec
;
101 # Number of whole seconds of elapsed time.
106 # Rest of the elapsed time (a fraction of a second).
108 # Number of nanoseconds.
110 return self-
>tv_nsec
;
113 # Elapsed time in microseconds, with both whole seconds and the rest
115 # May cause an `Int` overflow, use only with a low number of seconds.
117 return self-
>tv_sec
*1000000 + self-
>tv_nsec
/1000;
120 # Elapsed time in milliseconds, with both whole seconds and the rest
122 # May cause an `Int` overflow, use only with a low number of seconds.
124 return self-
>tv_sec
*1000 + self-
>tv_nsec
/1000000;
127 # Number of seconds as a `Float`
129 # Incurs a loss of precision, but the result is pretty to print.
131 return (double
)self-
>tv_sec
+ 0.000000001 * self-
>tv_nsec
;
134 redef fun to_s do return "{to_f}s"
137 # Keeps track of real time
140 # var clock = new Clock
142 # # sleeping at least 1s
144 # assert clock.total >= 1.0
145 # assert clock.lapse >= 1.0
147 # # sleeping at least 5ms
149 # assert clock.total >= 1.005
150 # assert clock.lapse >= 0.005
153 super FinalizableOnce
155 # TODO use less mallocs
158 private var time_at_beginning = new Timespec.monotonic_now
160 # Time at last time a lapse method was called
161 private var time_at_last_lapse = new Timespec.monotonic_now
163 private var temp = new Timespec.monotonic_now
165 # Smallest time frame reported by clock
166 private fun resolution: Timespec `{
167 struct timespec
* tv
= malloc
( sizeof
(struct timespec
) );
168 #if defined(__MACH__) && !defined(CLOCK_REALTIME)
171 mach_msg_type_number_t count
;
172 host_get_clock_service
(mach_host_self
(), SYSTEM_CLOCK, &cclock
);
173 clock_get_attributes
(cclock
, CLOCK_GET_TIME_RES, (clock_attr_t
)&nsecs
, &count
);
174 mach_port_deallocate
(mach_task_self
(), cclock
);
178 clock_getres
( CLOCK_MONOTONIC, tv
);
183 # Seconds since the creation of this instance
188 now.minus(now, time_at_beginning)
192 # Seconds since the last call to `lapse
`
195 var time_at_last_lapse = time_at_last_lapse
198 time_at_last_lapse.minus(now, time_at_last_lapse)
199 var r = time_at_last_lapse.to_f
201 self.temp = time_at_last_lapse
202 self.time_at_last_lapse = now
207 # Seconds since the last call to `lapse
`, without resetting the lapse counter
208 fun peek_lapse: Float
212 now.minus(now, time_at_last_lapse)
216 redef fun finalize_once
218 time_at_beginning.free
219 time_at_last_lapse.free