draw closure in cfv optimisation
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
CommitLineData
9c312311 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
ffd54a90 19
3d218f2a 20#include <lttv/hook.h>
eccb5352 21
22
dc877563 23typedef struct _LttvHookClosure {
47e76340 24 LttvHook hook;
25 void *hook_data;
26 LttvHookPrio prio;
8436038a 27 guint ref_count;
dc877563 28} LttvHookClosure;
eccb5352 29
47e76340 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
eccb5352 37
dc877563 38LttvHooks *lttv_hooks_new()
39{
40 return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
eccb5352 41}
42
dc877563 43
44void lttv_hooks_destroy(LttvHooks *h)
45{
2a2fa4f0 46 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
eccb5352 47 g_array_free(h, TRUE);
48}
49
eccb5352 50
47e76340 51void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p)
dc877563 52{
bb545b3c 53 LttvHookClosure *c, new_c;
54 guint i;
55
dc877563 56 if(h == NULL)g_error("Null hook added");
eccb5352 57
bb545b3c 58 new_c.hook = f;
59 new_c.hook_data = hook_data;
60 new_c.prio = p;
5a6db8b4 61 new_c.ref_count = 1;
8436038a 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
bb545b3c 75 for(i = 0; i < h->len; i++) {
bb545b3c 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);
eccb5352 84}
85
bb545b3c 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)
dc877563 97{
8436038a 98 guint i,j,k;
bb545b3c 99 LttvHookClosure *c;
100 const LttvHookClosure *new_c;
dc877563 101
ffd54a90 102 if(list == NULL) return;
bb545b3c 103 for(i = 0, j = 0 ; i < list->len; i++) {
104 new_c = &g_array_index(list, LttvHookClosure, i);
8436038a 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++;
bb545b3c 117 break;
118 }
bb545b3c 119 }
8436038a 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 }
bb545b3c 136 }
dc877563 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) {
8436038a 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 }
dc877563 162 }
163 }
164 return NULL;
165}
166
167
168void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
eccb5352 169{
dc877563 170 unsigned i;
171
172 LttvHookClosure *c;
eccb5352 173
174 for(i = 0 ; i < h->len ; i++) {
dc877563 175 c = &g_array_index(h, LttvHookClosure, i);
176 if(c->hook == f && c->hook_data == hook_data) {
8436038a 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 }
dc877563 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
ffd54a90 196 if(list == NULL) return;
dc877563 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) {
8436038a 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 }
dc877563 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 }
eccb5352 220 }
221}
222
223
dc877563 224unsigned lttv_hooks_number(LttvHooks *h)
225{
226 return h->len;
227}
eccb5352 228
dc877563 229
47e76340 230void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
231 LttvHookPrio *p)
dc877563 232{
233 LttvHookClosure *c;
234
47e76340 235 if(i >= h->len)
236 {
237 *f = NULL;
238 *hook_data = NULL;
239 *p = 0;
240 return;
241 }
242
dc877563 243 c = &g_array_index(h, LttvHookClosure, i);
244 *f = c->hook;
245 *hook_data = c->hook_data;
47e76340 246 *p = c->prio;
dc877563 247}
248
249
ffd54a90 250void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
dc877563 251{
ffd54a90 252 g_array_remove_index(h, i);
dc877563 253}
254
dc877563 255gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
256{
b445142a 257 gboolean ret, sum_ret = FALSE;
dc877563 258
259 LttvHookClosure *c;
260
ffd54a90 261 guint i;
262
dc877563 263 if(h != NULL) {
264 for(i = 0 ; i < h->len ; i++) {
265 c = &g_array_index(h, LttvHookClosure, i);
b445142a 266 ret = c->hook(c->hook_data,call_data);
267 sum_ret = sum_ret || ret;
dc877563 268 }
269 }
b445142a 270 return sum_ret;
dc877563 271}
272
273
274gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
275{
276 LttvHookClosure *c;
277
ffd54a90 278 guint i;
279
dc877563 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
47e76340 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
f210b68b 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);
47e76340 315 ret = c1->hook(c1->hook_data,call_data1);
316 sum_ret = sum_ret || ret;
47e76340 317 }
f210b68b 318 for(;j < h2->len; j++) {
319 c2 = &g_array_index(h2, LttvHookClosure, j);
47e76340 320 ret = c2->hook(c2->hook_data,call_data2);
321 sum_ret = sum_ret || ret;
f210b68b 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;
47e76340 328 }
329 }
f210b68b 330 } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */
331 for(j = 0 ; j < h2->len ; j++) {
47e76340 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
f210b68b 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);
47e76340 365 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
47e76340 366 }
f210b68b 367 for(;j < h2->len; j++) {
368 c2 = &g_array_index(h2, LttvHookClosure, j);
47e76340 369 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
f210b68b 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;
47e76340 375 }
376 }
f210b68b 377 } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */
47e76340 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 }
f210b68b 383
47e76340 384 return FALSE;
385
386}
387
dc877563 388
389LttvHooksById *lttv_hooks_by_id_new()
390{
eccb5352 391 return g_ptr_array_new();
392}
393
394
dc877563 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 }
eccb5352 402 g_ptr_array_free(h, TRUE);
403}
404
405
ffd54a90 406LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
eccb5352 407{
dc877563 408 if(h->len <= id) g_ptr_array_set_size(h, id + 1);
eccb5352 409 if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
dc877563 410 return h->pdata[id];
eccb5352 411}
412
dc877563 413
414unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
eccb5352 415{
dc877563 416 return h->len;
417}
418
dc877563 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 }
eccb5352 425}
426
This page took 0.048936 seconds and 4 git commands to generate.