This PR updates the main services of `Clock` to return float values instead of malloced extern instances of `Timespec`. There is a precision loss, but it's sufficient for games and the likes, and a program needing higher precision can still use `Timespec` directly. Clients don't even have to worry about memory management anymore.
Pull-Request: #2117
Reviewed-by: Jean Privat <jean@pryen.org>
game.save
end
- # Maximum wanted frame per second
- var max_fps = 30
-
- # clock used to track FPS
- private var clock = new Clock
-
redef fun frame_core(display)
do
game.step
game.draw(display)
- var dt = clock.lapse
- var target_dt = 1000000000 / max_fps
- if dt.sec == 0 and dt.nanosec < target_dt then
- var sleep_t = target_dt - dt.nanosec
- sys.nanosleep(0, sleep_t)
- end
end
redef fun input(input_event)
var dt = clock.lapse
tick += 1
- var turn = new TTurn(self, tick, dt.to_f, dt.millisec)
+ var turn = new TTurn(self, tick, dt, ((dt-dt.floor)*1000.0).to_i)
return turn
end
private var frame_count = 0
# Deadline used to compute `current_fps`
- private var frame_count_deadline = 5
+ private var frame_count_deadline = 5.0
# Check and sleep to maintain a frame-rate bellow `maximum_fps`
#
# Is automatically called at the end of `full_frame`.
fun limit_fps
do
- var t = clock.total.sec
+ var t = clock.total
if t >= frame_count_deadline then
var cfps = frame_count.to_f / 5.0
self.current_fps = cfps
frame_count = 0
- frame_count_deadline = t + 5
+ frame_count_deadline = t + 5.0
end
frame_count += 1
private var frame_count = 0
# Deadline used to compute `current_fps`
- private var frame_count_deadline = 0
+ private var frame_count_deadline = 0.0
# Check and sleep to maitain a frame-rate bellow `maximum_fps`
# Also periodically uptate `current_fps`
# Is automatically called at the end of `full_frame`.
fun limit_fps
do
- var t = clock.total.sec
+ var t = clock.total
if t >= frame_count_deadline then
var cfps = frame_count.to_f / 5.0
self.current_fps = cfps
frame_count = 0
- frame_count_deadline = t + 5
+ frame_count_deadline = t + 5.0
end
frame_count += 1
# Total execution time of this event
var sum = 0.0
- # Register a new event execution time with a `Timespec`
- fun add(lapse: Timespec) do add_float lapse.to_f
-
- # Register a new event execution time in seconds using a `Float`
- fun add_float(time: Float)
+ # Register a new event execution time in seconds
+ fun add(time: Float)
do
if time.to_f < min.to_f or count == 0 then min = time
if time.to_f > max.to_f then max = time
redef fun all(req, res) do
var timer = req.timer
if timer != null then
- print "{req.method} {req.uri} {res.color_status} ({timer.total})"
+ print "{req.method} {req.uri} {res.color_status} ({timer.total}s)"
else
print "{req.method} {req.uri} {res.color_status}"
end
redef fun all(req, res) do
var timer = req.timer
if timer != null then
- print "{req.method} {req.uri} {res.color_status} ({timer.total})"
+ print "{req.method} {req.uri} {res.color_status} ({timer.total}s)"
else
print "{req.method} {req.uri} {res.color_status}"
end
redef fun all(req, res) do
var clock = req.clock
if clock != null then
- print "{req.method} {req.uri} {status(res)} ({clock.total})"
+ print "{req.method} {req.uri} {status(res)} ({clock.total}s)"
else
print "{req.method} {req.uri} {status(res)}"
end
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.
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
- # Time at instanciation
+ super FinalizableOnce
+
+ # TODO use less mallocs
+
+ # Time at creation
protected 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
# Smallest time frame reported by clock
- fun resolution : Timespec `{
+ fun resolution: Timespec `{
struct timespec* tv = malloc( sizeof(struct timespec) );
#ifdef __MACH__
clock_serv_t cclock;
return tv;
`}
- # Return timelapse since instanciation of this instance
- fun total : Timespec
+ # Seconds since the creation of this instance
+ fun total: Float
do
- return new Timespec.monotonic_now - time_at_beginning
+ var now = new Timespec.monotonic_now
+ var diff = now - time_at_beginning
+ var r = diff.to_f
+ diff.free
+ now.free
+ return r
end
- # Return timelapse since last call to lapse
- fun lapse : Timespec
+ # 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
- return dt
+ 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
+ end
+
+ redef fun finalize_once
+ do
+ time_at_beginning.free
+ time_at_last_lapse.free
end
end
srcs.add_all mmodule.ffi_files
# Compiler options specific to this module
- var ldflags = mmodule.ldflags[""].join(" ")
+ var ldflags_array = mmodule.ldflags[""]
+ if ldflags_array.has("-lrt") and system("sh -c 'uname -s 2>/dev/null || echo not' | grep Darwin >/dev/null") == 0 then
+ # Remove -lrt on OS X
+ ldflags_array.remove "-lrt"
+ end
+ var ldflags = ldflags_array.join(" ")
# Protect pkg-config
var pkgconfigs = mmodule.pkgconfigs
+++ /dev/null
-sleeping 1s
-true
-true
-sleeping 5000ns
-true
-true
-true
var p = new Process("sleep", "10")
# Send some signals
-p.signal(sigalarm)
+p.signal sigalarm
p.kill
# Wait for it to die
p.wait
-var lapse = clock.lapse
# Let's be generous here, as long as it does not take 5 secs out of 10 it's OK
-print lapse.sec < 5
+print clock.lapse < 5.0
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012 Alexis Laferrière <alexis.laf@xymus.net>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import realtime
-
-redef extern class Timespec
- fun simplify : Int
- do
- return sec*1000000 + nanosec/1000
- end
-end
-
-var c = new Clock
-var t0 = c.total.simplify
-
-print "sleeping 1s"
-nanosleep(1, 0)
-print c.total.sec >= 1
-print c.lapse.sec >= 1
-
-var t1 = c.total.simplify
-
-print "sleeping 5000ns"
-nanosleep(0, 5000)
-print c.lapse.nanosec >= 5000
-
-var t2 = c.total.simplify
-
-print t0 <= t1
-print t1 <= t2