Implement DBUS timeout functions

This commit is contained in:
Kovid Goyal 2018-07-09 21:00:12 +05:30
parent 99ea6c08a7
commit 8e665ffedc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 62 additions and 7 deletions

27
glfw/backend_utils.c vendored
View File

@ -12,11 +12,25 @@
#include <string.h>
#include <errno.h>
#include <float.h>
#include <time.h>
#ifdef __NetBSD__
#define ppoll pollts
#endif
static inline double
monotonic() {
struct timespec ts = {0};
#ifdef CLOCK_HIGHRES
clock_gettime(CLOCK_HIGHRES, &ts);
#elif CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
}
void
update_fds(EventLoopData *eld) {
eld->fds_count = 0;
@ -73,7 +87,6 @@ toggleWatch(EventLoopData *eld, id_type watch_id, int enabled) {
}
static id_type timer_counter = 0;
extern double glfwGetTime(void);
static int
compare_timers(const void *a_, const void *b_) {
@ -91,7 +104,7 @@ addTimer(EventLoopData *eld, double interval, int enabled, timer_callback_func c
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) return 0;
Timer *t = eld->timers + eld->timers_count++;
t->interval = interval;
t->trigger_at = enabled ? glfwGetTime() + interval : DBL_MAX;
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
t->callback = cb;
t->callback_data = cb_data;
t->id = ++timer_counter;
@ -108,7 +121,7 @@ void
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
for (nfds_t i = 0; i < eld->timers_count; i++) {
if (eld->timers[i].id == timer_id) {
double trigger_at = enabled ? (glfwGetTime() + eld->timers[i].interval) : DBL_MAX;
double trigger_at = enabled ? (monotonic() + eld->timers[i].interval) : DBL_MAX;
if (trigger_at != eld->timers[i].trigger_at) {
eld->timers[i].trigger_at = trigger_at;
update_timers(eld);
@ -133,7 +146,7 @@ double
prepareForPoll(EventLoopData *eld, double timeout) {
for (nfds_t i = 0; i < eld->fds_count; i++) eld->fds[i].revents = 0;
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return timeout;
double now = glfwGetTime(), next_repeat_at = eld->timers[0].trigger_at;
double now = monotonic(), next_repeat_at = eld->timers[0].trigger_at;
if (timeout < 0 || now + timeout > next_repeat_at) {
timeout = next_repeat_at <= now ? 0 : next_repeat_at - now;
}
@ -165,7 +178,7 @@ dispatchTimers(EventLoopData *eld) {
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return 0;
static struct { timer_callback_func func; id_type id; void* data; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
unsigned num_dispatches = 0;
double now = glfwGetTime();
double now = monotonic();
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at < DBL_MAX; i++) {
if (eld->timers[i].trigger_at <= now) {
eld->timers[i].trigger_at = now + eld->timers[i].interval;
@ -201,7 +214,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
int read_ok = 0;
timeout = prepareForPoll(eld, timeout);
int result;
double end_time = glfwGetTime() + timeout;
double end_time = monotonic() + timeout;
while(1) {
if (timeout >= 0) {
@ -212,7 +225,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
read_ok = eld->watches[0].ready;
break;
}
timeout = end_time - glfwGetTime();
timeout = end_time - monotonic();
if (timeout <= 0) break;
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
break;

42
glfw/dbus_glfw.c vendored
View File

@ -76,6 +76,7 @@ add_dbus_watch(DBusWatch *watch, void *data) {
if (!watch_id) return FALSE;
id_type *idp = malloc(sizeof(id_type));
if (!idp) return FALSE;
*idp = watch_id;
dbus_watch_set_data(watch, idp, free);
return TRUE;
}
@ -92,6 +93,41 @@ toggle_dbus_watch(DBusWatch *watch, void *data) {
if (idp) toggleWatch(dbus_data->eld, *idp, dbus_watch_get_enabled(watch));
}
static void
on_dbus_timer_ready(id_type timer_id, void *data) {
DBusTimeout *t = (DBusTimeout*)data;
dbus_timeout_handle(t);
}
static dbus_bool_t
add_dbus_timeout(DBusTimeout *timeout, void *data) {
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
if (interval < 0) return FALSE;
id_type timer_id = addTimer(dbus_data->eld, interval, enabled, on_dbus_timer_ready, timeout);
if (!timer_id) return FALSE;
id_type *idp = malloc(sizeof(id_type));
if (!idp) return FALSE;
*idp = timer_id;
dbus_timeout_set_data(timeout, idp, free);
return TRUE;
}
static void
remove_dbus_timeout(DBusTimeout *timeout, void *data) {
id_type *idp = dbus_timeout_get_data(timeout);
if (idp) removeTimer(dbus_data->eld, *idp);
}
static void
toggle_dbus_timeout(DBusTimeout *timeout, void *data) {
id_type *idp = dbus_timeout_get_data(timeout);
if (idp) toggleTimer(dbus_data->eld, *idp, dbus_timeout_get_enabled(timeout));
}
DBusConnection*
glfw_dbus_connect_to(const char *path, const char* err_msg) {
DBusError err;
@ -114,6 +150,12 @@ glfw_dbus_connect_to(const char *path, const char* err_msg) {
dbus_connection_unref(ans);
return NULL;
}
if (!dbus_connection_set_timeout_functions(ans, add_dbus_timeout, remove_dbus_timeout, toggle_dbus_timeout, NULL, NULL)) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set DBUS timeout functions on connection to: %s", path);
dbus_connection_close(ans);
dbus_connection_unref(ans);
return NULL;
}
return ans;
}