/* * atheme-services: A collection of minimalist IRC services * event.c: Event subsystem. * * Copyright (c) 2005-2007 Atheme Project (http://www.atheme.org) * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "atheme.h" #include "internal.h" const char *last_event_ran = NULL; struct ev_entry event_table[MAX_EVENTS]; static time_t event_time_min = -1; static unsigned int event_add_real(const char *name, EVH *func, void *arg, time_t when, time_t frequency) { unsigned int i; /* find the first inactive index */ for (i = 0; i < MAX_EVENTS; i++) { if (!event_table[i].active) { event_table[i].func = func; event_table[i].name = name; event_table[i].arg = arg; event_table[i].when = CURRTIME + when; event_table[i].frequency = frequency; event_table[i].active = true; if (event_table[i].when < event_time_min && event_time_min != -1) event_time_min = event_table[i].when; slog(LG_DEBUG, "event_add_real(): added %s to event table", name); claro_state.event++; return i; } } /* failed to add it... */ slog(LG_DEBUG, "event_add_real(): failed to add %s to event table", name); return -1; } /* add an event to the table to be continually ran */ unsigned int event_add(const char *name, EVH *func, void *arg, time_t when) { return event_add_real(name, func, arg, when, when); } /* adds an event to the table to be ran only once */ unsigned int event_add_once(const char *name, EVH *func, void *arg, time_t when) { return event_add_real(name, func, arg, when, 0); } /* delete an event from the table */ void event_delete(EVH *func, void *arg) { int i = event_find(func, arg); if (i == -1) return; slog(LG_DEBUG, "event_delete(): removing \"%s\"", event_table[i].name); if (last_event_ran == event_table[i].name) last_event_ran = ""; event_table[i].name = NULL; event_table[i].func = NULL; event_table[i].arg = NULL; event_table[i].active = false; claro_state.event--; } /* checks all pending events */ void event_run(void) { unsigned int i; for (i = 0; i < MAX_EVENTS; i++) { if (event_table[i].active && (event_table[i].when <= CURRTIME)) { /* now we call it */ last_event_ran = event_table[i].name; event_table[i].func(event_table[i].arg); event_time_min = -1; /* event is scheduled more than once */ if (event_table[i].frequency) event_table[i].when = CURRTIME + event_table[i].frequency; else { /* not nice but we need to play safe */ last_event_ran = ""; event_table[i].name = NULL; event_table[i].func = NULL; event_table[i].arg = NULL; event_table[i].active = false; claro_state.event--; } } } } /* returns the time the next event_run() should happen */ time_t event_next_time(void) { unsigned int i; if (event_time_min == -1) { for (i = 0; i < MAX_EVENTS; i++) { if (event_table[i].active && ((event_table[i].when < event_time_min) || event_time_min == -1)) event_time_min = event_table[i].when; } } return event_time_min; } /* initializes event system */ void event_init(void) { last_event_ran = NULL; memset((void *)event_table, 0, sizeof(event_table)); } /* finds an event in the table */ unsigned int event_find(EVH *func, void *arg) { unsigned int i; for (i = 0; i < MAX_EVENTS; i++) { if ((event_table[i].func == func) && (event_table[i].arg == arg)) return i; } return -1; } /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs * vim:ts=8 * vim:sw=8 * vim:noexpandtab */