Wrap tick API
This avoids to use the SDL timer API directly, and will allow to handle generic ticks (possibly negative).
This commit is contained in:
parent
5524f378c8
commit
ec871dd3f5
8 changed files with 58 additions and 16 deletions
|
@ -25,6 +25,7 @@ src = [
|
|||
'src/util/process.c',
|
||||
'src/util/str_util.c',
|
||||
'src/util/thread.c',
|
||||
'src/util/tick.c',
|
||||
]
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#include "fps_counter.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define FPS_COUNTER_INTERVAL_MS 1000
|
||||
#define FPS_COUNTER_INTERVAL SC_TICK_FROM_SEC(1)
|
||||
|
||||
bool
|
||||
fps_counter_init(struct fps_counter *counter) {
|
||||
|
@ -47,7 +46,7 @@ set_started(struct fps_counter *counter, bool started) {
|
|||
static void
|
||||
display_fps(struct fps_counter *counter) {
|
||||
unsigned rendered_per_second =
|
||||
counter->nr_rendered * 1000 / FPS_COUNTER_INTERVAL_MS;
|
||||
counter->nr_rendered * SC_TICK_FREQ / FPS_COUNTER_INTERVAL;
|
||||
if (counter->nr_skipped) {
|
||||
LOGI("%u fps (+%u frames skipped)", rendered_per_second,
|
||||
counter->nr_skipped);
|
||||
|
@ -68,8 +67,8 @@ check_interval_expired(struct fps_counter *counter, uint32_t now) {
|
|||
counter->nr_skipped = 0;
|
||||
// add a multiple of the interval
|
||||
uint32_t elapsed_slices =
|
||||
(now - counter->next_timestamp) / FPS_COUNTER_INTERVAL_MS + 1;
|
||||
counter->next_timestamp += FPS_COUNTER_INTERVAL_MS * elapsed_slices;
|
||||
(now - counter->next_timestamp) / FPS_COUNTER_INTERVAL + 1;
|
||||
counter->next_timestamp += FPS_COUNTER_INTERVAL * elapsed_slices;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -82,11 +81,11 @@ run_fps_counter(void *data) {
|
|||
sc_cond_wait(&counter->state_cond, &counter->mutex);
|
||||
}
|
||||
while (!counter->interrupted && is_started(counter)) {
|
||||
uint32_t now = SDL_GetTicks();
|
||||
sc_tick now = sc_tick_now();
|
||||
check_interval_expired(counter, now);
|
||||
|
||||
assert(counter->next_timestamp > now);
|
||||
uint32_t remaining = counter->next_timestamp - now;
|
||||
sc_tick remaining = counter->next_timestamp - now;
|
||||
|
||||
// ignore the reason (timeout or signaled), we just loop anyway
|
||||
sc_cond_timedwait(&counter->state_cond, &counter->mutex, remaining);
|
||||
|
@ -99,7 +98,7 @@ run_fps_counter(void *data) {
|
|||
bool
|
||||
fps_counter_start(struct fps_counter *counter) {
|
||||
sc_mutex_lock(&counter->mutex);
|
||||
counter->next_timestamp = SDL_GetTicks() + FPS_COUNTER_INTERVAL_MS;
|
||||
counter->next_timestamp = sc_tick_now() + FPS_COUNTER_INTERVAL;
|
||||
counter->nr_rendered = 0;
|
||||
counter->nr_skipped = 0;
|
||||
sc_mutex_unlock(&counter->mutex);
|
||||
|
@ -165,7 +164,7 @@ fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
|||
}
|
||||
|
||||
sc_mutex_lock(&counter->mutex);
|
||||
uint32_t now = SDL_GetTicks();
|
||||
sc_tick now = sc_tick_now();
|
||||
check_interval_expired(counter, now);
|
||||
++counter->nr_rendered;
|
||||
sc_mutex_unlock(&counter->mutex);
|
||||
|
@ -178,7 +177,7 @@ fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
|||
}
|
||||
|
||||
sc_mutex_lock(&counter->mutex);
|
||||
uint32_t now = SDL_GetTicks();
|
||||
sc_tick now = sc_tick_now();
|
||||
check_interval_expired(counter, now);
|
||||
++counter->nr_skipped;
|
||||
sc_mutex_unlock(&counter->mutex);
|
||||
|
|
|
@ -24,7 +24,7 @@ struct fps_counter {
|
|||
bool interrupted;
|
||||
unsigned nr_rendered;
|
||||
unsigned nr_skipped;
|
||||
uint32_t next_timestamp;
|
||||
sc_tick next_timestamp;
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
|
@ -554,10 +554,10 @@ server_stop(struct server *server) {
|
|||
sc_mutex_lock(&server->mutex);
|
||||
bool signaled = false;
|
||||
if (!server->process_terminated) {
|
||||
#define WATCHDOG_DELAY_MS 1000
|
||||
#define WATCHDOG_DELAY SC_TICK_FROM_SEC(1)
|
||||
signaled = sc_cond_timedwait(&server->process_terminated_cond,
|
||||
&server->mutex,
|
||||
WATCHDOG_DELAY_MS);
|
||||
WATCHDOG_DELAY);
|
||||
}
|
||||
sc_mutex_unlock(&server->mutex);
|
||||
|
||||
|
|
|
@ -123,7 +123,12 @@ sc_cond_wait(sc_cond *cond, sc_mutex *mutex) {
|
|||
}
|
||||
|
||||
bool
|
||||
sc_cond_timedwait(sc_cond *cond, sc_mutex *mutex, uint32_t ms) {
|
||||
sc_cond_timedwait(sc_cond *cond, sc_mutex *mutex, sc_tick delay) {
|
||||
if (delay < 0) {
|
||||
return false; // timeout
|
||||
}
|
||||
|
||||
uint32_t ms = SC_TICK_TO_MS(delay);
|
||||
int r = SDL_CondWaitTimeout(cond->cond, mutex->mutex, ms);
|
||||
#ifndef NDEBUG
|
||||
if (r < 0) {
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct SDL_Thread SDL_Thread;
|
||||
|
@ -72,7 +73,7 @@ sc_cond_wait(sc_cond *cond, sc_mutex *mutex);
|
|||
|
||||
// return true on signaled, false on timeout
|
||||
bool
|
||||
sc_cond_timedwait(sc_cond *cond, sc_mutex *mutex, uint32_t ms);
|
||||
sc_cond_timedwait(sc_cond *cond, sc_mutex *mutex, sc_tick ms);
|
||||
|
||||
void
|
||||
sc_cond_signal(sc_cond *cond);
|
||||
|
|
16
app/src/util/tick.c
Normal file
16
app/src/util/tick.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "tick.h"
|
||||
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
sc_tick
|
||||
sc_tick_now(void) {
|
||||
// SDL_GetTicks() resolution is in milliseconds, but sc_tick are expressed
|
||||
// in microseconds to store PTS without precision loss.
|
||||
//
|
||||
// As an alternative, SDL_GetPerformanceCounter() and
|
||||
// SDL_GetPerformanceFrequency() could be used, but:
|
||||
// - the conversions (avoiding overflow) are expansive, since the
|
||||
// frequency is not known at compile time;
|
||||
// - in practice, we don't need more precision for now.
|
||||
return (sc_tick) SDL_GetTicks() * 1000;
|
||||
}
|
20
app/src/util/tick.h
Normal file
20
app/src/util/tick.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef SC_TICK_H
|
||||
#define SC_TICK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int64_t sc_tick;
|
||||
#define SC_TICK_FREQ 1000000 // microsecond
|
||||
|
||||
// To be adapted if SC_TICK_FREQ changes
|
||||
#define SC_TICK_TO_US(tick) (tick)
|
||||
#define SC_TICK_TO_MS(tick) ((tick) / 1000)
|
||||
#define SC_TICK_TO_SEC(tick) ((tick) / 1000000)
|
||||
#define SC_TICK_FROM_US(us) (us)
|
||||
#define SC_TICK_FROM_MS(ms) ((ms) * 1000)
|
||||
#define SC_TICK_FROM_SEC(sec) ((sec) * 1000000)
|
||||
|
||||
sc_tick
|
||||
sc_tick_now(void);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue