]> jfr.im git - irc/quakenet/newserv.git/blob - core/hooks-new.c
fix: warning: format not a string literal and no format arguments
[irc/quakenet/newserv.git] / core / hooks-new.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 count;
21 int alive;
22 int dirty;
23 Hook *head;
24 } HookHead;
25
26 static HookHead hooks[HOOKMAX];
27 static int dirtyhooks[HOOKMAX];
28 static int dirtyhookcount;
29
30 unsigned int hookqueuelength = 0;
31
32 static void defraghook(HookHead *h);
33 static void markdirty(int hook);
34
35 void inithooks() {
36 }
37
38 int registerhook(int hooknum, HookCallback callback) {
39 return registerpriorityhook(hooknum, callback, PRIORITY_DEFAULT);
40 }
41
42 int registerpriorityhook(int hooknum, HookCallback callback, long priority) {
43 Hook *hp, *pred, *n;
44 HookHead *h;
45
46 if(hooknum>HOOKMAX)
47 return 1;
48
49 if(hookqueuelength > 0)
50 Error("core", ERR_WARNING, "Attempting to register hook %d inside a hook queue: %p", hooknum, callback);
51
52 for(pred=NULL,h=&hooks[hooknum],hp=h->head;hp;hp=hp->next) {
53 if(hp->callback==callback)
54 return 1;
55 if(priority>=hp->priority)
56 pred=hp;
57 }
58
59 n = malloc(sizeof(Hook));
60 n->priority = priority;
61 n->callback = callback;
62 n->flags = 0;
63
64 if(!pred) {
65 n->next = h->head;
66 h->head = n;
67 } else {
68 n->next = pred->next;
69 pred->next = n;
70 }
71
72 if(h->count > 0)
73 markdirty(hooknum);
74
75 h->count++;
76 h->alive++;
77
78 return 0;
79 }
80
81 int deregisterhook(int hooknum, HookCallback callback) {
82 Hook *hp;
83 HookHead *h;
84
85 if (hooknum>HOOKMAX)
86 return 1;
87
88 if(hookqueuelength > 0)
89 Error("core", ERR_WARNING, "Attempting to deregister hook %d inside a hook queue: %p", hooknum, callback);
90
91 for(h=&hooks[hooknum],hp=h->head;hp;hp=hp->next) {
92 if(hp->callback==callback) {
93 markdirty(hooknum);
94 hp->callback = NULL;
95 h->alive--;
96 return 0;
97 }
98 }
99
100 return 1;
101 }
102
103 void triggerhook(int hooknum, void *arg) {
104 int i;
105 Hook *hp;
106
107 if (hooknum>HOOKMAX)
108 return;
109
110 hookqueuelength++;
111 for(hp=hooks[hooknum].head;hp;hp=hp->next) {
112 if(hp->callback)
113 (hp->callback)(hooknum, arg);
114 }
115 hookqueuelength--;
116
117 for(i=0;i<dirtyhookcount;i++) {
118 defraghook(&hooks[dirtyhooks[i]]);
119 }
120 dirtyhookcount=0;
121
122 if (!hookqueuelength && hooknum!=HOOK_CORE_ENDOFHOOKSQUEUE)
123 triggerhook(HOOK_CORE_ENDOFHOOKSQUEUE, 0);
124 }
125
126 static void markdirty(int hook) {
127 if(hooks[hook].dirty)
128 return;
129
130 hooks[hook].dirty = 1;
131 dirtyhooks[dirtyhookcount++] = hook;
132 }
133
134 /* Non compacting version
135 static void defraghook(HookHead *h) {
136 Hook *hp, *pp, *np;
137
138 for(pp=NULL,hp=h->head;hp;hp=np) {
139 np=hp->next;
140 if(hp->callback==NULL) {
141 free(hp);
142 } else {
143 if(pp==NULL) {
144 h->head = hp;
145 } else {
146 pp->next = hp;
147 }
148 pp = hp;
149 }
150 }
151 if(!pp) {
152 h->head = NULL;
153 } else {
154 pp->next = NULL;
155 }
156
157 h->dirty = 0;
158 h->count = h->alive;
159 }
160 */
161
162 static void defraghook(HookHead *h) {
163 Hook *hp, *pp, *np;
164 Hook *n, *nstart;
165 Hook *contig = NULL;
166
167 if(h->alive != 0) {
168 nstart = n = malloc(sizeof(Hook) * h->alive);
169 } else {
170 nstart = n = NULL;
171 }
172
173 for(pp=NULL,hp=h->head;hp;hp=np) {
174 np=hp->next;
175 if(!contig && (hp->flags & HF_CONTIGUOUS))
176 contig = hp;
177
178 if(hp->callback==NULL) {
179 if(!(hp->flags & HF_CONTIGUOUS))
180 free(hp);
181 } else {
182 memcpy(n, hp, sizeof(Hook));
183
184 n->flags|=HF_CONTIGUOUS;
185
186 if(pp!=NULL)
187 pp->next = n;
188 pp = n++;
189 }
190 }
191
192 if(contig)
193 free(contig);
194
195 assert(!(nstart && !pp) && !(!nstart && pp));
196
197 h->head = nstart;
198 if(pp)
199 pp->next = NULL;
200
201 h->dirty = 0;
202 h->count = h->alive;
203 }