core :: union_find
union–find algorithm using an efficient disjoint-set data structureglesv2 :: opengles2_hello_triangle
Basic example of OpenGL ES 2.0 usage using SDL 2performance_analysis :: performance_analysis
Services to gather information on the performance of events by categoriesgamnit :: camera_control_android
Two fingers camera manipulation, pinch to zoom and slide to scrollEulerCamera
and App::frame_core_draw
to get a stereoscopic view
# Services to keep time of the wall clock time
module realtime is ldflags "-lrt"
in "C header" `{
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#define _POSIX_C_SOURCE 199309L
#include <time.h>
`}
in "C" `{
#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 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);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts->tv_sec = mts.tv_sec;
ts->tv_nsec = mts.tv_nsec;
}
#else
#define nit_clock_gettime clock_gettime
#endif
`}
# Elapsed time representation.
private 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) );
nit_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;
tv->tv_nsec = other->tv_nsec;
return tv;
`}
# Update `self` clock.
fun update `{
nit_clock_gettime(CLOCK_MONOTONIC, self);
`}
# Subtract `other` from `self`
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 `{
return self->tv_sec;
`}
# Rest of the elapsed time (a fraction of a second).
#
# Number of nanoseconds.
fun nanosec : Int `{
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;
`}
# Number of seconds as a `Float`
#
# Incurs a loss of precision, but the result is pretty to print.
fun to_f: Float `{
return (double)self->tv_sec + 0.000000001 * self->tv_nsec;
`}
redef fun to_s do return "{to_f}s"
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
super FinalizableOnce
# TODO use less mallocs
# Time at creation
private var time_at_beginning = new Timespec.monotonic_now
# Time at last time a lapse method was called
private var time_at_last_lapse = new Timespec.monotonic_now
private var temp = new Timespec.monotonic_now
# Smallest time frame reported by clock
private fun resolution: Timespec `{
struct timespec* tv = malloc( sizeof(struct timespec) );
#if (defined(__MACH__) || defined(TARGET_OS_IPHONE)) && !defined(CLOCK_REALTIME)
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;
`}
# Seconds since the creation of this instance
fun total: Float
do
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 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 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
lib/realtime/realtime.nit:13,1--234,3