draw closure in cfv optimisation
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
... / ...
CommitLineData
1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20#include <lttv/hook.h>
21
22
23typedef struct _LttvHookClosure {
24 LttvHook hook;
25 void *hook_data;
26 LttvHookPrio prio;
27 guint ref_count;
28} LttvHookClosure;
29
30gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b)
31{
32 if(a->prio < b->prio) return -1;
33 if(a->prio > b->prio) return 1;
34 return 0;
35}
36
37
38LttvHooks *lttv_hooks_new()
39{
40 return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
41}
42
43
44void lttv_hooks_destroy(LttvHooks *h)
45{
46 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
47 g_array_free(h, TRUE);
48}
49
50
51void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p)
52{
53 LttvHookClosure *c, new_c;
54 guint i;
55
56 if(h == NULL)g_error("Null hook added");
57
58 new_c.hook = f;
59 new_c.hook_data = hook_data;
60 new_c.prio = p;
61 new_c.ref_count = 1;
62
63 /* Preliminary check for duplication */
64 /* only hook and hook data is checked */
65 for(i = 0; i < h->len; i++) {
66 c = &g_array_index(h, LttvHookClosure, i);
67 if(new_c.hook == c->hook && new_c.hook_data == c->hook_data) {
68 g_assert(new_c.prio == c->prio);
69 c->ref_count++;
70 return;
71 }
72 }
73
74
75 for(i = 0; i < h->len; i++) {
76 c = &g_array_index(h, LttvHookClosure, i);
77 if(new_c.prio < c->prio) {
78 g_array_insert_val(h,i,new_c);
79 return;
80 }
81 }
82 if(i == h->len)
83 g_array_append_val(h,new_c);
84}
85
86/* lttv_hooks_add_list
87 *
88 * Adds a sorted list into another sorted list.
89 *
90 * Note : h->len is modified, but only incremented. This assures
91 * its coherence through the function.
92 *
93 * j is an index to the element following the last one added in the
94 * destination array.
95 */
96void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list)
97{
98 guint i,j,k;
99 LttvHookClosure *c;
100 const LttvHookClosure *new_c;
101
102 if(list == NULL) return;
103 for(i = 0, j = 0 ; i < list->len; i++) {
104 new_c = &g_array_index(list, LttvHookClosure, i);
105 gboolean found=FALSE;
106
107 /* Preliminary check for duplication */
108 /* only hook and hook data is checked, not priority */
109 for(k = 0; k < h->len; k++) {
110 c = &g_array_index(h, LttvHookClosure, k);
111 if(new_c->hook == c->hook && new_c->hook_data == c->hook_data) {
112 /* Found another identical entry : increment its ref_count and
113 * jump over the source index */
114 g_assert(new_c->prio == c->prio);
115 found=TRUE;
116 c->ref_count++;
117 break;
118 }
119 }
120
121 if(!found) {
122 /* If not found, add it to the destination array */
123 while(j < h->len) {
124 c = &g_array_index(h, LttvHookClosure, j);
125 if(new_c->prio < c->prio) {
126 g_array_insert_val(h,j,*new_c);
127 j++;
128 break;
129 }
130 else j++;
131 }
132 if(j == h->len) {
133 g_array_append_val(h,*new_c);
134 j++;
135 }
136 }
137 }
138}
139
140
141void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
142{
143 unsigned i;
144
145 void *hook_data;
146
147 LttvHookClosure *c;
148
149 for(i = 0 ; i < h->len ; i++) {
150 c = &g_array_index(h, LttvHookClosure, i);
151 if(c->hook == f) {
152 if(c->ref_count == 1) {
153 hook_data = c->hook_data;
154 lttv_hooks_remove_by_position(h, i);
155 return hook_data;
156 } else {
157 g_assert(c->ref_count != 0);
158 c->ref_count--;
159 return NULL; /* We do not want anyone to free a hook_data
160 still referenced */
161 }
162 }
163 }
164 return NULL;
165}
166
167
168void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
169{
170 unsigned i;
171
172 LttvHookClosure *c;
173
174 for(i = 0 ; i < h->len ; i++) {
175 c = &g_array_index(h, LttvHookClosure, i);
176 if(c->hook == f && c->hook_data == hook_data) {
177 if(c->ref_count == 1) {
178 lttv_hooks_remove_by_position(h, i);
179 return;
180 } else {
181 g_assert(c->ref_count != 0);
182 c->ref_count--;
183 return;
184 }
185 }
186 }
187}
188
189
190void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
191{
192 guint i, j;
193
194 LttvHookClosure *c, *c_list;
195
196 if(list == NULL) return;
197 for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
198 c = &g_array_index(h, LttvHookClosure, i);
199 c_list = &g_array_index(list, LttvHookClosure, j);
200 if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
201 if(c->ref_count == 1) {
202 lttv_hooks_remove_by_position(h, i);
203 } else {
204 g_assert(c->ref_count != 0);
205 c->ref_count--;
206 }
207 j++;
208 }
209 else i++;
210 }
211
212 /* Normally the hooks in h are ordered as in list. If this is not the case,
213 try harder here. */
214
215 if(j < list->len) {
216 for(; j < list->len ; j++) {
217 c_list = &g_array_index(list, LttvHookClosure, j);
218 lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
219 }
220 }
221}
222
223
224unsigned lttv_hooks_number(LttvHooks *h)
225{
226 return h->len;
227}
228
229
230void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
231 LttvHookPrio *p)
232{
233 LttvHookClosure *c;
234
235 if(i >= h->len)
236 {
237 *f = NULL;
238 *hook_data = NULL;
239 *p = 0;
240 return;
241 }
242
243 c = &g_array_index(h, LttvHookClosure, i);
244 *f = c->hook;
245 *hook_data = c->hook_data;
246 *p = c->prio;
247}
248
249
250void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
251{
252 g_array_remove_index(h, i);
253}
254
255gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
256{
257 gboolean ret, sum_ret = FALSE;
258
259 LttvHookClosure *c;
260
261 guint i;
262
263 if(h != NULL) {
264 for(i = 0 ; i < h->len ; i++) {
265 c = &g_array_index(h, LttvHookClosure, i);
266 ret = c->hook(c->hook_data,call_data);
267 sum_ret = sum_ret || ret;
268 }
269 }
270 return sum_ret;
271}
272
273
274gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
275{
276 LttvHookClosure *c;
277
278 guint i;
279
280 for(i = 0 ; i < h->len ; i++) {
281 c = &g_array_index(h, LttvHookClosure, i);
282 if(c->hook(c->hook_data,call_data)) return TRUE;
283 }
284 return FALSE;
285}
286
287gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
288 LttvHooks *h2, void *call_data2)
289{
290 gboolean ret, sum_ret = FALSE;
291
292 LttvHookClosure *c1, *c2;
293
294 guint i, j;
295
296 if(h1 != NULL) {
297 if(h2 != NULL) {
298 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
299 c1 = &g_array_index(h1, LttvHookClosure, i);
300 c2 = &g_array_index(h2, LttvHookClosure, j);
301 if(c1->prio <= c2->prio) {
302 ret = c1->hook(c1->hook_data,call_data1);
303 sum_ret = sum_ret || ret;
304 i++;
305 }
306 else {
307 ret = c2->hook(c2->hook_data,call_data2);
308 sum_ret = sum_ret || ret;
309 j++;
310 }
311 }
312 /* Finish the last list with hooks left */
313 for(;i < h1->len; i++) {
314 c1 = &g_array_index(h1, LttvHookClosure, i);
315 ret = c1->hook(c1->hook_data,call_data1);
316 sum_ret = sum_ret || ret;
317 }
318 for(;j < h2->len; j++) {
319 c2 = &g_array_index(h2, LttvHookClosure, j);
320 ret = c2->hook(c2->hook_data,call_data2);
321 sum_ret = sum_ret || ret;
322 }
323 } else { /* h1 != NULL && h2 == NULL */
324 for(i = 0 ; i < h1->len ; i++) {
325 c1 = &g_array_index(h1, LttvHookClosure, i);
326 ret = c1->hook(c1->hook_data,call_data1);
327 sum_ret = sum_ret || ret;
328 }
329 }
330 } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */
331 for(j = 0 ; j < h2->len ; j++) {
332 c2 = &g_array_index(h2, LttvHookClosure, j);
333 ret = c2->hook(c2->hook_data,call_data2);
334 sum_ret = sum_ret || ret;
335 }
336 }
337
338 return sum_ret;
339}
340
341gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
342 LttvHooks *h2, void *call_data2)
343{
344 LttvHookClosure *c1, *c2;
345
346 guint i, j;
347
348 if(h1 != NULL) {
349 if(h2 != NULL) {
350 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
351 c1 = &g_array_index(h1, LttvHookClosure, i);
352 c2 = &g_array_index(h2, LttvHookClosure, j);
353 if(c1->prio <= c2->prio) {
354 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
355 i++;
356 }
357 else {
358 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
359 j++;
360 }
361 }
362 /* Finish the last list with hooks left */
363 for(;i < h1->len; i++) {
364 c1 = &g_array_index(h1, LttvHookClosure, i);
365 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
366 }
367 for(;j < h2->len; j++) {
368 c2 = &g_array_index(h2, LttvHookClosure, j);
369 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
370 }
371 } else { /* h2 == NULL && h1 != NULL */
372 for(i = 0 ; i < h1->len ; i++) {
373 c1 = &g_array_index(h1, LttvHookClosure, i);
374 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
375 }
376 }
377 } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */
378 for(j = 0 ; j < h2->len ; j++) {
379 c2 = &g_array_index(h2, LttvHookClosure, j);
380 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
381 }
382 }
383
384 return FALSE;
385
386}
387
388
389LttvHooksById *lttv_hooks_by_id_new()
390{
391 return g_ptr_array_new();
392}
393
394
395void lttv_hooks_by_id_destroy(LttvHooksById *h)
396{
397 guint i;
398
399 for(i = 0 ; i < h->len ; i++) {
400 if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
401 }
402 g_ptr_array_free(h, TRUE);
403}
404
405
406LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
407{
408 if(h->len <= id) g_ptr_array_set_size(h, id + 1);
409 if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
410 return h->pdata[id];
411}
412
413
414unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
415{
416 return h->len;
417}
418
419void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
420{
421 if(id < h->len && h->pdata[id] != NULL) {
422 lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
423 h->pdata[id] = NULL;
424 }
425}
426
This page took 0.023146 seconds and 4 git commands to generate.