Scheduling code

Richard Wilson richard.wilson at tinct.net
Mon Feb 14 11:27:03 GMT 2011


Skipped content of type multipart/alternative-------------- next part --------------
/*
 * Copyright 2008 Vincent Sanders <vince at simtec.co.uk>
 * Copyright 2011 Richard Wilson <richard.wilson at tinct.net>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

#include <sys/time.h>
#include <time.h>

#include "desktop/browser.h"
#include "windows/schedule.h"
#include "utils/utils.h"
#include "utils/log.h"

/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;

/**
 * scheduled callback.
 */
struct nscallback
{
	struct nscallback *next;
	struct timeval tv;
	void (*callback)(void *p);
	void *p;
};


/**
 * Schedule a callback.
 *
 * \param  cs_ival   interval before the callback should be made / cs
 * \param  callback  callback function
 * \param  p         user parameter, passed to callback function
 *
 * The callback function will be called as soon as possible after t cs have
 * passed.
 */

void schedule(int cs_ival, void (*callback)(void *p), void *p)
{
	struct nscallback *nscb;
	struct nscallback *cur_nscb;
	struct timeval tv;

	tv.tv_sec = cs_ival / 100; /* cs to seconds */
	tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */

	nscb = calloc(1, sizeof(struct nscallback));

	LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, cs_ival));

	gettimeofday(&nscb->tv, NULL);
	timeradd(&nscb->tv, &tv, &nscb->tv);

	nscb->callback = callback;
	nscb->p = p;

	/* should we link at the head of the list? */
	if ((schedule_list == NULL) || (timercmp(&schedule_list->tv, &nscb->tv, >=))) {
		nscb->next = schedule_list;
		schedule_list = nscb;
		return;
	}
	/* find the element we should link in after */
	cur_nscb = schedule_list;
	while ((cur_nscb->next != NULL) && (timercmp(&cur_nscb->next->tv, &nscb->tv, <)))
		cur_nscb = cur_nscb->next;
	nscb->next = cur_nscb->next;
	cur_nscb->next = nscb;
}

/**
 * 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.
 */

void schedule_remove(void (*callback)(void *p), void *p)
{
	struct nscallback *cur_nscb;
	struct nscallback *prev_nscb;
	struct nscallback *unlnk_nscb;

	if (schedule_list == NULL)
		return;

	LOG(("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 */
			LOG(("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;
		}
	}
}

/**
 * Process scheduled callbacks up to current time.
 *
 * @return The number of milliseconds untill the next scheduled event
 * or -1 for no event.
 */

int schedule_run(void)
{
	struct timeval tv;
	struct timeval rettime;
	struct nscallback *unlnk_nscb;

	if (schedule_list == NULL)
		return -1;

	gettimeofday(&tv, NULL);

	while ((schedule_list != NULL) && (timercmp(&tv, &schedule_list->tv, >=))) {
		/* remove callback */
		unlnk_nscb = schedule_list;
		schedule_list = schedule_list->next;

		LOG(("callback entry %p running %p(%p)",
				 unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));

		/* call callback */
		unlnk_nscb->callback(unlnk_nscb->p);

		free(unlnk_nscb);
	}

	if (schedule_list == NULL)
		return -1;

	/* make rettime relative to now */
	timersub(&schedule_list->tv, &tv, &rettime);

	/*LOG(("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);
}

/**
 * Output a list of the current scheduled callbacks.
 */

void list_schedule(void)
{
	struct timeval tv;
	struct nscallback *cur_nscb;

	gettimeofday(&tv, NULL);

	LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec));

	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;
	}
}


/*
 * Local Variables:
 * c-basic-offset:8
 * End:
 */
-------------- next part --------------
/*
 * Copyright 2011 Richard Wilson <richard.wilson at tinct.net>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */


#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "desktop/browser.h"
#include "windows/schedule.h"
#include "utils/log.h"
#include "utils/utils.h"

extern bool verbose_log = true;

void test_schedule(void *v);

int main(void)
{

	schedule(300, test_schedule, (void *)1);
	schedule(200, test_schedule, (void *)2);
	schedule(100, test_schedule, (void *)3);
	schedule(400, test_schedule, (void *)4);
	schedule(250, test_schedule, (void *)5);
	schedule(50, test_schedule, (void *)6);

	list_schedule();

	while (schedule_run() != -1);

	return 0;
}

void test_schedule(void *p) {
}


More information about the netsurf-dev mailing list