]> jfr.im git - irc/quakenet/newserv.git/blob - core/hooks.c
Remove old hooks.
[irc/quakenet/newserv.git] / core / hooks.c
1 /* hooks.c */
2
3 #include "hooks.h"
4 #include <assert.h>
5 #include "../core/error.h"
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9
10 #define HF_CONTIGUOUS 0x01
11
12 typedef struct Hook {
13 HookCallback callback;
14 long priority;
15 short flags;
16 struct Hook *next;
17 } Hook;
18
19 typedef struct HookHead {
20 int dirty;
21 Hook *head;
22 } HookHead;
23
24 static HookHead hooks[HOOKMAX];
25 static int dirtyhooks[HOOKMAX];
26 static int dirtyhookcount;
27
28 unsigned int hookqueuelength = 0;
29
30 static void collectgarbage(HookHead *h);
31 static void markdirty(int hook);
32
33 void inithooks() {
34 }
35
36 int registerhook(int hooknum, HookCallback callback) {
37 return registerpriorityhook(hooknum, callback, PRIORITY_DEFAULT);
38 }
39
40 int registerpriorityhook(int hooknum, HookCallback callback, long priority) {
41 Hook *hp, *pred, *n;
42 HookHead *h;
43
44 if(hooknum>HOOKMAX)
45 return 1;
46
47 if(hookqueuelength > 0)
48 Error("core", ERR_WARNING, "Attempting to register hook %d inside a hook queue: %p", hooknum, callback);
49
50 for(pred=NULL,h=&hooks[hooknum],hp=h->head;hp;hp=hp->next) {
51 if(hp->callback==callback)
52 return 1;
53 if(priority>=hp->priority)
54 pred=hp;
55 }
56
57 n = malloc(sizeof(Hook));
58 n->priority = priority;
59 n->callback = callback;
60 n->flags = 0;
61
62 if(!pred) {
63 n->next = h->head;
64 h->head = n;
65 } else {
66 n->next = pred->next;
67 pred->next = n;
68 }
69
70 return 0;
71 }
72
73 int deregisterhook(int hooknum, HookCallback callback) {
74 Hook *hp;
75 HookHead *h;
76
77 if (hooknum>HOOKMAX)
78 return 1;
79
80 if(hookqueuelength > 0)
81 Error("core", ERR_WARNING, "Attempting to deregister hook %d inside a hook queue: %p", hooknum, callback);
82
83 for(h=&hooks[hooknum],hp=h->head;hp;hp=hp->next) {
84 if(hp->callback==callback) {
85 markdirty(hooknum);
86 hp->callback = NULL;
87 return 0;
88 }
89 }
90
91 return 1;
92 }
93
94 void triggerhook(int hooknum, void *arg) {
95 int i;
96 Hook *hp;
97
98 if (hooknum>HOOKMAX)
99 return;
100
101 hookqueuelength++;
102 for(hp=hooks[hooknum].head;hp;hp=hp->next) {
103 if(hp->callback)
104 (hp->callback)(hooknum, arg);
105 }
106 hookqueuelength--;
107
108 if (!hookqueuelength && hooknum!=HOOK_CORE_ENDOFHOOKSQUEUE) {
109 triggerhook(HOOK_CORE_ENDOFHOOKSQUEUE, 0);
110
111 for(i=0;i<dirtyhookcount;i++) {
112 collectgarbage(&hooks[dirtyhooks[i]]);
113 }
114 dirtyhookcount=0;
115 }
116 }
117
118 static void markdirty(int hook) {
119 if(hooks[hook].dirty)
120 return;
121
122 hooks[hook].dirty = 1;
123 dirtyhooks[dirtyhookcount++] = hook;
124 }
125
126 static void collectgarbage(HookHead *h) {
127 Hook *hp, *pp, *np;
128
129 for(pp=NULL,hp=h->head;hp;hp=np) {
130 np=hp->next;
131 if(hp->callback==NULL) {
132 free(hp);
133 } else {
134 if(pp==NULL) {
135 h->head = hp;
136 } else {
137 pp->next = hp;
138 }
139 pp = hp;
140 }
141 }
142 if(!pp) {
143 h->head = NULL;
144 } else {
145 pp->next = NULL;
146 }
147
148 h->dirty = 0;
149 }