From 5d3c38a704e2e13fae7ed93e9029fa4543c8525b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 12 Feb 2016 13:36:12 +0000 Subject: remove reliance on GLib from monkey frontend This changes the monkey implemntation to use a simple scheduler list and select instead of glib events. --- content/fetch.c | 2 +- monkey/Makefile.target | 3 +- monkey/main.c | 77 ++++++++++++-- monkey/poll.c | 140 ------------------------ monkey/poll.h | 26 ----- monkey/schedule.c | 284 +++++++++++++++++++++++++++++++------------------ monkey/schedule.h | 34 ++++-- 7 files changed, 282 insertions(+), 284 deletions(-) delete mode 100644 monkey/poll.c delete mode 100644 monkey/poll.h diff --git a/content/fetch.c b/content/fetch.c index 2307676d3..47e6fc88e 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -379,7 +379,7 @@ fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops) return NSERROR_OK; } -/* exported interface documented in content/fetch.h */ +/* exported interface documented in content/fetchers.h */ nserror fetcher_fdset(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, diff --git a/monkey/Makefile.target b/monkey/Makefile.target index 281e82b98..3c7b093af 100644 --- a/monkey/Makefile.target +++ b/monkey/Makefile.target @@ -33,7 +33,6 @@ LDFLAGS += -lm # non optional pkg-configed libs $(eval $(call pkg_config_find_and_add,libcurl,Curl )) $(eval $(call pkg_config_find_and_add,openssl,OpenSSL)) -$(eval $(call pkg_config_find_and_add,glib-2.0,GLib2)) # optional pkg-config configured libraries $(eval $(call pkg_config_find_and_add_enabled,NSSVG,libsvgtiny,SVG)) @@ -58,7 +57,7 @@ endif # S_MONKEY are sources purely for the MONKEY build S_MONKEY := main.c utils.c filetype.c schedule.c bitmap.c plot.c browser.c \ - download.c 401login.c cert.c font.c poll.c dispatch.c fetch.c + download.c 401login.c cert.c font.c dispatch.c fetch.c S_MONKEY := $(addprefix monkey/,$(S_MONKEY)) diff --git a/monkey/main.c b/monkey/main.c index 9610ffff6..9569f9754 100644 --- a/monkey/main.c +++ b/monkey/main.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include +#include +#include #include "utils/config.h" #include "utils/log.h" @@ -26,12 +30,12 @@ #include "utils/filepath.h" #include "utils/nsoption.h" #include "content/urldb.h" +#include "content/fetchers.h" #include "content/fetchers/resource.h" #include "content/hlcache.h" #include "desktop/gui_misc.h" #include "desktop/netsurf.h" -#include "monkey/poll.h" #include "monkey/dispatch.h" #include "monkey/browser.h" #include "monkey/cert.h" @@ -238,6 +242,70 @@ static struct gui_browser_table monkey_browser_table = { .login = gui_401login_open, }; +static void monkey_run(void) +{ + fd_set read_fd_set, write_fd_set, exc_fd_set; + int max_fd; + int rdy_fd; + int schedtm; + struct timeval tv; + struct timeval* timeout; + + while (!monkey_done) { + + /* clears fdset */ + fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); + + /* add stdin to the set */ + if (max_fd < 0) { + max_fd = 0; + } + FD_SET(0, &read_fd_set); + FD_SET(0, &exc_fd_set); + + /* discover the next scheduled event time */ + schedtm = monkey_schedule_run(); + + /* setup timeout */ + switch (schedtm) { + case -1: + LOG("Iterate blocking"); + fprintf(stdout, "GENERIC POLL BLOCKING\n"); + timeout = NULL; + break; + + case 0: + LOG("Iterate immediate"); + tv.tv_sec = 0; + tv.tv_usec = 0; + timeout = &tv; + break; + + default: + LOG("Iterate non-blocking"); + fprintf(stdout, "GENERIC POLL TIMED\n"); + tv.tv_sec = schedtm / 1000; /* miliseconds to seconds */ + tv.tv_usec = (schedtm % 1000) * 1000; /* remainder to microseconds */ + timeout = &tv; + break; + } + + rdy_fd = select(max_fd + 1, + &read_fd_set, + &write_fd_set, + &exc_fd_set, + timeout); + if (rdy_fd < 0) { + monkey_done = true; + } else if (rdy_fd > 0) { + if (FD_ISSET(0, &read_fd_set)) { + monkey_process_command(); + } + } + } + +} + int main(int argc, char **argv) { @@ -300,8 +368,6 @@ main(int argc, char **argv) urldb_load(nsoption_charp(url_file)); urldb_load_cookies(nsoption_charp(cookie_file)); - monkey_prepare_input(); - ret = monkey_register_handler("QUIT", quit_handler); if (ret != NSERROR_OK) { die("quit handler failed to register"); @@ -313,10 +379,7 @@ main(int argc, char **argv) } fprintf(stdout, "GENERIC STARTED\n"); - - while (!monkey_done) { - monkey_poll(); - } + monkey_run(); fprintf(stdout, "GENERIC CLOSING_DOWN\n"); monkey_kill_browser_windows(); diff --git a/monkey/poll.c b/monkey/poll.c deleted file mode 100644 index 3ec31af86..000000000 --- a/monkey/poll.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2011 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 "content/hlcache.h" -#include "content/fetchers.h" - -#include "monkey/schedule.h" -#include "monkey/dispatch.h" -#include "monkey/poll.h" - -#ifdef DEBUG_POLL_LOOP -#include "utils/log.h" -#else -#define LOG(fmt, args...) ((void) 0) -#endif - - -#include - -typedef struct { - GSource gs; - GPollFD pf; -} MonkeySource; - -static gboolean monkey_source_prepare(GSource *source, - gint *timeout_) -{ - *timeout_ = -1; - return FALSE; -} - - -static gboolean monkey_source_check(GSource *source) -{ - MonkeySource *ms = (MonkeySource *)source; - if (ms->pf.revents & G_IO_IN) { - return TRUE; - } - return FALSE; -} - -static gboolean monkey_source_dispatch(GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - monkey_process_command(); - return TRUE; -} - -static void monkey_source_finalize(GSource *source) -{ - -} - -GSourceFuncs monkey_source_funcs = { - .prepare = monkey_source_prepare, - .check = monkey_source_check, - .dispatch = monkey_source_dispatch, - .finalize = monkey_source_finalize, -}; - -void -monkey_prepare_input(void) -{ - MonkeySource *gs = (MonkeySource *)g_source_new(&monkey_source_funcs, sizeof *gs); - gs->pf.fd = 0; - gs->pf.events = G_IO_IN | G_IO_ERR; - g_source_add_poll((GSource *)gs, &gs->pf); - g_source_attach((GSource *)gs, NULL); -} - -void monkey_poll(void) -{ - fd_set read_fd_set, write_fd_set, exc_fd_set; - int max_fd; - GPollFD *fd_list[1000]; - unsigned int fd_count = 0; - bool block = true; - - fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); - for (int i = 0; i <= max_fd; i++) { - if (FD_ISSET(i, &read_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG("Want to read %d", i); - } - if (FD_ISSET(i, &write_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_OUT | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG("Want to write %d", i); - } - if (FD_ISSET(i, &exc_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG("Want to check %d", i); - } - } - - schedule_run(); - - LOG("Iterate %sblocking", block ? "" : "non-"); - if (block) { - fprintf(stdout, "GENERIC POLL BLOCKING\n"); - } - g_main_context_iteration(g_main_context_default(), block); - - for (unsigned int i = 0; i != fd_count; i++) { - g_main_context_remove_poll(0, fd_list[i]); - free(fd_list[i]); - } - -} - diff --git a/monkey/poll.h b/monkey/poll.h deleted file mode 100644 index 2b14e61bd..000000000 --- a/monkey/poll.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 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 . - */ - -#ifndef NETSURF_MONKEY_POLL_H -#define NETSURF_MONKEY_POLL_H 1 - -void monkey_prepare_input(void); - -void monkey_poll(void); - -#endif /* NETSURF_MONKEY_POLL_H */ diff --git a/monkey/schedule.c b/monkey/schedule.c index d6f8e65dc..b3b335900 100644 --- a/monkey/schedule.c +++ b/monkey/schedule.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 Daniel Silverstone + * Copyright 2012 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -16,128 +16,208 @@ * along with this program. If not, see . */ -#include +#include +#include #include -#include -#include "utils/errors.h" +#include "utils/log.h" #include "monkey/schedule.h" -#undef DEBUG_MONKEY_SCHEDULE - -#ifdef DEBUG_MONKEY_SCHEDULE -#include "utils/log.h" +#ifdef DEBUG_SCHEDULER +#define SRLOG(x...) LOG(x) #else -#define LOG(fmt, args...) ((void) 0) +#define SRLOG(x...) ((void) 0) #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) +/* linked list of scheduled callbacks */ +static struct nscallback *schedule_list = NULL; + +/** + * scheduled callback. + */ +struct nscallback { - _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); - LOG("CB %p(%p) now pending run", cb->callback, cb->context); - pending_callbacks = g_list_append(pending_callbacks, cb); - return FALSE; + struct nscallback *next; + struct timeval tv; + void (*callback)(void *p); + void *p; +}; + +/** + * Unschedule a callback. + * + * \param callback callback function + * \param p user parameter, passed to callback function + * + * All scheduled callbacks matching both callback and p are removed. + */ +static nserror schedule_remove(void (*callback)(void *p), void *p) +{ + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; + + /* check there is something on the list to remove */ + if (schedule_list == NULL) { + return NSERROR_OK; + } + + SRLOG("removing %p, %p", callback, p); + + cur_nscb = schedule_list; + prev_nscb = NULL; + + while (cur_nscb != NULL) { + if ((cur_nscb->callback == callback) && + (cur_nscb->p == p)) { + /* item to remove */ + + SRLOG("callback entry %p removing %p(%p)", + cur_nscb, cur_nscb->callback, cur_nscb->p); + + /* remove callback */ + unlnk_nscb = cur_nscb; + cur_nscb = unlnk_nscb->next; + + if (prev_nscb == NULL) { + schedule_list = cur_nscb; + } else { + prev_nscb->next = cur_nscb; + } + free (unlnk_nscb); + } else { + /* move to next element */ + prev_nscb = cur_nscb; + cur_nscb = prev_nscb->next; + } + } + + return NSERROR_OK; } -static void -nsgtk_schedule_kill_callback(void *_target, void *_match) +/* exported function documented in framebuffer/schedule.h */ +nserror monkey_schedule(int tival, void (*callback)(void *p), void *p) { - _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; - } + struct nscallback *nscb; + struct timeval tv; + nserror ret; + + /* ensure uniqueness of the callback and context */ + ret = schedule_remove(callback, p); + if ((tival < 0) || (ret != NSERROR_OK)) { + return ret; + } + + SRLOG("Adding %p(%p) in %d", callback, p, tival); + + tv.tv_sec = tival / 1000; /* miliseconds to seconds */ + tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */ + + nscb = calloc(1, sizeof(struct nscallback)); + + gettimeofday(&nscb->tv, NULL); + timeradd(&nscb->tv, &tv, &nscb->tv); + + nscb->callback = callback; + nscb->p = p; + + /* add to list front */ + nscb->next = schedule_list; + schedule_list = nscb; + + return NSERROR_OK; } -static void -schedule_remove(void (*callback)(void *p), void *p) +/* exported function documented in framebuffer/schedule.h */ +int monkey_schedule_run(void) { - _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); + struct timeval tv; + struct timeval nexttime; + struct timeval rettime; + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; + + if (schedule_list == NULL) + return -1; + + /* reset enumeration to the start of the list */ + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; + + gettimeofday(&tv, NULL); + + while (cur_nscb != NULL) { + if (timercmp(&tv, &cur_nscb->tv, >)) { + /* scheduled time */ + + /* remove callback */ + unlnk_nscb = cur_nscb; + + if (prev_nscb == NULL) { + schedule_list = unlnk_nscb->next; + } else { + prev_nscb->next = unlnk_nscb->next; + } + + unlnk_nscb->callback(unlnk_nscb->p); + + free(unlnk_nscb); + + /* need to deal with callback modifying the list. */ + if (schedule_list == NULL) + return -1; /* no more callbacks scheduled */ + + /* reset enumeration to the start of the list */ + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; + } else { + /* if the time to the event is sooner than the + * currently recorded soonest event record it + */ + if (timercmp(&nexttime, &cur_nscb->tv, >)) { + nexttime = cur_nscb->tv; + } + /* move to next element */ + prev_nscb = cur_nscb; + cur_nscb = prev_nscb->next; + } + } + + /* make rettime relative to now */ + timersub(&nexttime, &tv, &rettime); + + SRLOG("returning time to next event as %ldms", + (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)); + + /* return next event time in milliseconds (24days max wait) */ + return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000); } -nserror monkey_schedule(int t, void (*callback)(void *p), void *p) +void monkey_schedule_list(void) { - _nsgtk_callback_t *cb; + struct timeval tv; + struct nscallback *cur_nscb; - /* Kill any pending schedule of this kind. */ - schedule_remove(callback, p); - if (t < 0) { - return NSERROR_OK; - } + gettimeofday(&tv, NULL); - cb = malloc(sizeof(_nsgtk_callback_t)); - cb->callback = callback; - cb->context = p; - cb->callback_killed = false; - /* Prepend is faster right now. */ - LOG("queued a callback to %p(%p) for %d msecs time", callback, p, t); - queued_callbacks = g_list_prepend(queued_callbacks, cb); - g_timeout_add(t, nsgtk_schedule_generic_callback, cb); + LOG("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec); - return NSERROR_OK; + cur_nscb = schedule_list; + while (cur_nscb != NULL) { + LOG("Schedule %p at %ld:%ld", + cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec); + cur_nscb = cur_nscb->next; + } } -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) { - LOG("CB DO %p(%p)", cb->callback, cb->context); - cb->callback(cb->context); - } else { - LOG("CB %p(%p) already dead, dropping", cb->callback, cb->context); - } - free(cb); - } - return true; -} + +/* + * Local Variables: + * c-basic-offset:2 + * End: + */ diff --git a/monkey/schedule.h b/monkey/schedule.h index 44ef9bf3b..14fad8247 100644 --- a/monkey/schedule.h +++ b/monkey/schedule.h @@ -1,5 +1,5 @@ /* - * Copyright 2006 Daniel Silverstone + * Copyright 2008 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -16,11 +16,33 @@ * along with this program. If not, see . */ -#ifndef NETSURF_GTK_CALLBACK_H -#define NETSURF_GTK_CALLBACK_H 1 +#ifndef NETSURF_MONKEY_SCHEDULE_H +#define NETSURF_MONKEY_SCHEDULE_H -nserror monkey_schedule(int t, void (*callback)(void *p), void *p); +/** + * Schedule a callback. + * + * \param tival interval before the callback should be made in ms + * \param callback callback function + * \param p user parameter, passed to callback function + * + * The callback function will be called as soon as possible after t ms have + * passed. + */ + +nserror monkey_schedule(int tival, void (*callback)(void *p), void *p); -bool schedule_run(void); +/** + * Process scheduled callbacks up to current time. + * + * @return The number of milliseconds untill the next scheduled event + * or -1 for no event. + */ +int monkey_schedule_run(void); + +/** + * Log a list of all scheduled callbacks. + */ +void monkey_schedule_list(void); -#endif /* NETSURF_GTK_CALLBACK_H */ +#endif -- cgit v1.2.3