From 7e85d15cb61229e9ba1b4a0f1f6c4ab19d436ac7 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 12 Mar 2011 15:08:07 +0000 Subject: Add a deaf monkey frontend. TODO: Make it listen svn path=/trunk/netsurf/; revision=11968 --- monkey/schedule.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 monkey/schedule.c (limited to 'monkey/schedule.c') diff --git a/monkey/schedule.c b/monkey/schedule.c new file mode 100644 index 000000000..9491ccb67 --- /dev/null +++ b/monkey/schedule.c @@ -0,0 +1,128 @@ +/* + * Copyright 2006-2007 Daniel Silverstone + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "desktop/browser.h" +#include "gtk/schedule.h" + +#ifdef DEBUG_GTK_SCHEDULE +#include "utils/log.h" +#else +#define LOG(X) +#endif + +/** Killable callback closure embodiment. */ +typedef struct { + void (*callback)(void *); /**< The callback function. */ + void *context; /**< The context for the callback. */ + bool callback_killed; /**< Whether or not this was killed. */ +} _nsgtk_callback_t; + +/** List of callbacks which have occurred and are pending running. */ +static GList *pending_callbacks = NULL; +/** List of callbacks which are queued to occur in the future. */ +static GList *queued_callbacks = NULL; +/** List of callbacks which are about to be run in this ::schedule_run. */ +static GList *this_run = NULL; + +static gboolean +nsgtk_schedule_generic_callback(gpointer data) +{ + _nsgtk_callback_t *cb = (_nsgtk_callback_t *)(data); + if (cb->callback_killed) { + /* This callback instance has been killed. */ + LOG(("CB at %p already dead.", cb)); + } + queued_callbacks = g_list_remove(queued_callbacks, cb); + pending_callbacks = g_list_append(pending_callbacks, cb); + return FALSE; +} + +static void +nsgtk_schedule_kill_callback(void *_target, void *_match) +{ + _nsgtk_callback_t *target = (_nsgtk_callback_t *)_target; + _nsgtk_callback_t *match = (_nsgtk_callback_t *)_match; + if ((target->callback == match->callback) && + (target->context == match->context)) { + LOG(("Found match for %p(%p), killing.", + target->callback, target->context)); + target->callback = NULL; + target->context = NULL; + target->callback_killed = true; + } +} + +void +schedule_remove(void (*callback)(void *p), void *p) +{ + _nsgtk_callback_t cb_match = { + .callback = callback, + .context = p, + }; + + g_list_foreach(queued_callbacks, + nsgtk_schedule_kill_callback, &cb_match); + g_list_foreach(pending_callbacks, + nsgtk_schedule_kill_callback, &cb_match); + g_list_foreach(this_run, + nsgtk_schedule_kill_callback, &cb_match); +} + +void +schedule(int t, void (*callback)(void *p), void *p) +{ + const int msec_timeout = t * 10; + _nsgtk_callback_t *cb = malloc(sizeof(_nsgtk_callback_t)); + /* Kill any pending schedule of this kind. */ + schedule_remove(callback, p); + cb->callback = callback; + cb->context = p; + cb->callback_killed = false; + /* Prepend is faster right now. */ + queued_callbacks = g_list_prepend(queued_callbacks, cb); + g_timeout_add(msec_timeout, nsgtk_schedule_generic_callback, cb); +} + +bool +schedule_run(void) +{ + /* Capture this run of pending callbacks into the list. */ + this_run = pending_callbacks; + + if (this_run == NULL) + return false; /* Nothing to do */ + + /* Clear the pending list. */ + pending_callbacks = NULL; + + LOG(("Captured a run of %d callbacks to fire.", g_list_length(this_run))); + + /* Run all the callbacks which made it this far. */ + while (this_run != NULL) { + _nsgtk_callback_t *cb = (_nsgtk_callback_t *)(this_run->data); + this_run = g_list_remove(this_run, this_run->data); + if (!cb->callback_killed) + cb->callback(cb->context); + free(cb); + } + return true; +} -- cgit v1.2.3