X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/526e7c1d302e1e08fe72db8c9fa7c14f4096c1b7..211567363bd8bfbd70cef81e4208ea02d49ebb55:/core/hooks.c diff --git a/core/hooks.c b/core/hooks.c index baf23b01..104e525c 100644 --- a/core/hooks.c +++ b/core/hooks.c @@ -2,73 +2,148 @@ #include "hooks.h" #include -#include "../lib/array.h" +#include "../core/error.h" +#include +#include +#include -array hooks[HOOKMAX]; +#define HF_CONTIGUOUS 0x01 + +typedef struct Hook { + HookCallback callback; + long priority; + short flags; + struct Hook *next; +} Hook; + +typedef struct HookHead { + int dirty; + Hook *head; +} HookHead; + +static HookHead hooks[HOOKMAX]; +static int dirtyhooks[HOOKMAX]; +static int dirtyhookcount; + +unsigned int hookqueuelength = 0; + +static void collectgarbage(HookHead *h); +static void markdirty(int hook); void inithooks() { - int i; - - hookqueuelength=0; - for (i=0;iHOOKMAX) + return registerpriorityhook(hooknum, callback, PRIORITY_DEFAULT); +} + +int registerpriorityhook(int hooknum, HookCallback callback, long priority) { + Hook *hp, *pred, *n; + HookHead *h; + + if(hooknum>HOOKMAX) return 1; - - hcbs=(HookCallback *)(hooks[hooknum].content); - for(i=0;i 0) + Error("core", ERR_WARNING, "Attempting to register hook %d inside a hook queue: %p", hooknum, callback); + + for(pred=NULL,h=&hooks[hooknum],hp=h->head;hp;hp=hp->next) { + if(hp->callback==callback) return 1; + if(priority>=hp->priority) + pred=hp; + } + + n = malloc(sizeof(Hook)); + n->priority = priority; + n->callback = callback; + n->flags = 0; + + if(!pred) { + n->next = h->head; + h->head = n; + } else { + n->next = pred->next; + pred->next = n; + } - i=array_getfreeslot(&hooks[hooknum]); - hcbs=(HookCallback *)(hooks[hooknum].content); - hcbs[i]=callback; - return 0; } int deregisterhook(int hooknum, HookCallback callback) { - int i; - HookCallback *hcbs; - + Hook *hp; + HookHead *h; + if (hooknum>HOOKMAX) return 1; - hcbs=(HookCallback *)(hooks[hooknum].content); + if(hookqueuelength > 0) + Error("core", ERR_WARNING, "Attempting to deregister hook %d inside a hook queue: %p", hooknum, callback); - for(i=0;ihead;hp;hp=hp->next) { + if(hp->callback==callback) { + markdirty(hooknum); + hp->callback = NULL; return 0; } + } return 1; } void triggerhook(int hooknum, void *arg) { int i; - HookCallback *hcbs; - + Hook *hp; + if (hooknum>HOOKMAX) return; hookqueuelength++; - hcbs=(HookCallback *)(hooks[hooknum].content); - for (i=0;inext) { + if(hp->callback) + (hp->callback)(hooknum, arg); } hookqueuelength--; - - if (!hookqueuelength && hooknum!=HOOK_CORE_ENDOFHOOKSQUEUE) + + if (!hookqueuelength && hooknum!=HOOK_CORE_ENDOFHOOKSQUEUE) { triggerhook(HOOK_CORE_ENDOFHOOKSQUEUE, 0); + + for(i=0;ihead;hp;hp=np) { + np=hp->next; + if(hp->callback==NULL) { + free(hp); + } else { + if(pp==NULL) { + h->head = hp; + } else { + pp->next = hp; + } + pp = hp; + } + } + if(!pp) { + h->head = NULL; + } else { + pp->next = NULL; + } + + h->dirty = 0; } -