Expose elapsed time API (#670)

This commit is contained in:
Matthias Melcher 2023-02-09 14:48:39 +01:00 committed by GitHub
parent 880fc26857
commit ffadc23cab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 123 additions and 28 deletions

View File

@ -470,6 +470,13 @@ public:
static void add_check(Fl_Timeout_Handler, void* = 0);
static int has_check(Fl_Timeout_Handler, void* = 0);
static void remove_check(Fl_Timeout_Handler, void* = 0);
static Fl_Timestamp now();
static double seconds_since(Fl_Timestamp& then);
static double seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back);
static long ticks_since(Fl_Timestamp& then);
static long ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back);
// private
static void run_idle();
static void run_checks();

View File

@ -12,6 +12,9 @@
* https://www.fltk.org/bugs.php
*/
#ifndef Fl_Platform_Types_H
#define Fl_Platform_Types_H
/** \file
Definitions of platform-dependent types.
The exact nature of these types varies with the platform.
@ -62,6 +65,13 @@ typedef opaque FL_SOCKET; /**< socket or file descriptor */
*/
typedef struct opaque *GLContext;
/**
Platform-specific point in time, used for delta time calculation.
\note This type may be a struct. sizeof(Fl_Timestamp) may be different on
different platforms. Fl_Timestamp may change with future ABI changes.
*/
typedef opaque Fl_Timestamp;
# define FL_COMMAND opaque /**< An alias for FL_CTRL on Windows and X11, or FL_META on MacOS X */
# define FL_CONTROL opaque /**< An alias for FL_META on Windows and X11, or FL_CTRL on MacOS X */
@ -127,4 +137,15 @@ extern FL_EXPORT int fl_control_modifier();
#endif /* FL_PLATFORM_TYPES_H */
// This is currently the same for all platforms, but may change in the future
struct Fl_Timestamp_t {
long sec;
long usec;
};
typedef struct Fl_Timestamp_t Fl_Timestamp;
#endif /* FL_DOXYGEN */
#endif /* Fl_Platform_Types_H */

View File

@ -2,7 +2,7 @@
// Timeout support functions for the Fast Light Tool Kit (FLTK).
//
// Author: Albrecht Schlosser
// Copyright 2021-2022 by Bill Spitzak and others.
// Copyright 2021-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -34,40 +34,108 @@ Fl_Timeout *Fl_Timeout::current_timeout = 0;
static int num_timers = 0; // DEBUG
#endif
// Internal timestamp, used for delta time calculation.
// Note: FLTK naming convention is not used here to avoid potential conflicts
// in the future.
/**
Set a time stamp at this point in time.
struct FlTimeStamp {
long sec;
long usec;
};
The time stamp is an opaque type and does not represent the time of day or
some time and date in the calendar. It is used with Fl::seconds_between() and
Fl::seconds_since() to measure elapsed time.
typedef struct FlTimeStamp FlTimeStamp_t;
\code
Fl_Timestamp start = Fl::now();
// do something
double s = Fl::seconds_since(start);
printf("That operation took %g seconds\n", s);
\endcode
// Get a timestamp of type FlTimeStamp.
Depending on the system the resolution may be milliseconds or microseconds.
Under certain conditions (particularly on Windows) the value in member `sec`
may wrap around and does not represent a real time (maybe runtime of the system).
Function seconds_since() below uses this to subtract two timestamps which is
always a correct delta time with milliseconds or microseconds resolution.
// Depending on the system the resolution may be milliseconds or microseconds.
// Under certain conditions (particularly on Windows) the value in member `sec'
// may wrap around and does not represent a real time (maybe runtime of the system).
// Function elapsed_time() below uses this to subtract two timestamps which is always
// a correct delta time with milliseconds or microseconds resolution.
\todo Fl::system_driver()->gettime() was implemented for the Forms library and
has a limited resolution (on Windows: milliseconds). On POSIX platforms it uses
gettimeofday() with microsecond resolution.
A new function could use a better resolution on Windows with its multimedia
timers which requires a new dependency: winmm.lib (dll). This could be a future
improvement, maybe set as a build option or generally (requires Win95 or 98?).
// To do: Fl::system_driver()->gettime() was implemented for the Forms library and
// has a limited resolution (on Windows: milliseconds). On POSIX platforms it uses
// gettimeofday() with microsecond resolution.
// A new function could use a better resolution on Windows with its multimedia
// timers which requires a new dependency: winmm.lib (dll). This could be a future
// improvement, maybe set as a build option or generally (requires Win95 or 98?).
\return this moment in time as an opaque time stamp
static void get_timestamp(FlTimeStamp_t *ts) {
\see Fl::seconds_since(Fl_Timestamp& then)
Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back)
Fl::ticks_since(Fl_Timestamp& then)
Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back)
*/
Fl_Timestamp Fl::now() {
Fl_Timestamp ts;
time_t sec;
int usec;
Fl::system_driver()->gettime(&sec, &usec);
ts->sec = (long)sec;
ts->usec = usec;
ts.sec = (long)sec;
ts.usec = usec;
return ts; // C++ will copy the result into the lvalue for us
}
/**
Return the time in seconds between now and a previously taken time stamp.
\param[in] then a previously taken time stamp
\return elapsed seconds and fractions of a second
\see Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back)
Fl::now()
*/
double Fl::seconds_since(Fl_Timestamp& then) {
Fl_Timestamp ts_now = Fl::now();
return Fl::seconds_between(ts_now, then);
}
/**
Return the time in seconds between two time stamps.
\param[in] back a previously taken time stamp
\param[in] further_back an even earlier time stamp
\return elapsed seconds and fractions of a second
\see Fl::seconds_since(Fl_Timestamp& then), Fl::now()
*/
double Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back) {
return double((back.sec - further_back.sec) + (back.usec - further_back.usec) / 1000000.);
}
/**
Return the time in ticks (60Hz) between now and a previously taken time stamp.
Ticks are a convenient way to time animations 'per frame'. Even though
modern computers use all kinds of screen refresh rates, 60Hz is a very good
base for animation that is typically shown in user interface graphics.
\param[in] then a previously taken time stamp
\return elapsed ticks in 60th of a second
\see Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back), Fl::now()
*/
long Fl::ticks_since(Fl_Timestamp& then) {
Fl_Timestamp ts_now = Fl::now();
return Fl::ticks_between(ts_now, then);
}
/**
Return the time in ticks (60Hz) between two time stamps.
\param[in] back a previously taken time stamp
\param[in] further_back an even earlier time stamp
\return elapsed ticks in 60th of a second
\see Fl::ticks_since(Fl_Timestamp& then), Fl::now()
*/
long Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back) {
return (back.sec-further_back.sec)*60 + (back.usec-further_back.usec)/16666;
}
// Returns 0 and initializes the "previous" timestamp when called for the first time.
/*
@ -83,14 +151,13 @@ static void get_timestamp(FlTimeStamp_t *ts) {
*/
static double elapsed_time() {
static int first = 1; // initialization
static FlTimeStamp_t prev; // previous timestamp
FlTimeStamp_t now; // current timestamp
static Fl_Timestamp prev; // previous timestamp
Fl_Timestamp now = Fl::now(); // current timestamp
double elapsed = 0.0;
get_timestamp(&now);
if (first) {
first = 0;
} else {
elapsed = double((now.sec - prev.sec) + (now.usec - prev.usec) / 1000000.);
elapsed = Fl::seconds_between(now, prev);
}
prev = now;
return elapsed;