removed many g_error and exit(1) from the tracefile reader
[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;
8436038a 61
62 /* Preliminary check for duplication */
63 /* only hook and hook data is checked */
64 for(i = 0; i < h->len; i++) {
65 c = &g_array_index(h, LttvHookClosure, i);
66 if(new_c.hook == c->hook && new_c.hook_data == c->hook_data) {
67 g_assert(new_c.prio == c->prio);
68 c->ref_count++;
69 return;
70 }
71 }
72
73
bb545b3c 74 for(i = 0; i < h->len; i++) {
bb545b3c 75 c = &g_array_index(h, LttvHookClosure, i);
76 if(new_c.prio < c->prio) {
77 g_array_insert_val(h,i,new_c);
78 return;
79 }
80 }
81 if(i == h->len)
82 g_array_append_val(h,new_c);
eccb5352 83}
84
bb545b3c 85/* lttv_hooks_add_list
86 *
87 * Adds a sorted list into another sorted list.
88 *
89 * Note : h->len is modified, but only incremented. This assures
90 * its coherence through the function.
91 *
92 * j is an index to the element following the last one added in the
93 * destination array.
94 */
95void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list)
dc877563 96{
8436038a 97 guint i,j,k;
bb545b3c 98 LttvHookClosure *c;
99 const LttvHookClosure *new_c;
dc877563 100
ffd54a90 101 if(list == NULL) return;
bb545b3c 102 for(i = 0, j = 0 ; i < list->len; i++) {
103 new_c = &g_array_index(list, LttvHookClosure, i);
8436038a 104 gboolean found=FALSE;
105
106 /* Preliminary check for duplication */
107 /* only hook and hook data is checked, not priority */
108 for(k = 0; k < h->len; k++) {
109 c = &g_array_index(h, LttvHookClosure, k);
110 if(new_c->hook == c->hook && new_c->hook_data == c->hook_data) {
111 /* Found another identical entry : increment its ref_count and
112 * jump over the source index */
113 g_assert(new_c->prio == c->prio);
114 found=TRUE;
115 c->ref_count++;
bb545b3c 116 break;
117 }
bb545b3c 118 }
8436038a 119
120 if(!found) {
121 /* If not found, add it to the destination array */
122 while(j < h->len) {
123 c = &g_array_index(h, LttvHookClosure, j);
124 if(new_c->prio < c->prio) {
125 g_array_insert_val(h,j,*new_c);
126 j++;
127 break;
128 }
129 else j++;
130 }
131 if(j == h->len) {
132 g_array_append_val(h,*new_c);
133 j++;
134 }
bb545b3c 135 }
dc877563 136 }
137}
138
139
140void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
141{
142 unsigned i;
143
144 void *hook_data;
145
146 LttvHookClosure *c;
147
148 for(i = 0 ; i < h->len ; i++) {
149 c = &g_array_index(h, LttvHookClosure, i);
150 if(c->hook == f) {
8436038a 151 if(c->ref_count == 1) {
152 hook_data = c->hook_data;
153 lttv_hooks_remove_by_position(h, i);
154 return hook_data;
155 } else {
156 g_assert(c->ref_count != 0);
157 c->ref_count--;
158 return NULL; /* We do not want anyone to free a hook_data
159 still referenced */
160 }
dc877563 161 }
162 }
163 return NULL;
164}
165
166
167void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
eccb5352 168{
dc877563 169 unsigned i;
170
171 LttvHookClosure *c;
eccb5352 172
173 for(i = 0 ; i < h->len ; i++) {
dc877563 174 c = &g_array_index(h, LttvHookClosure, i);
175 if(c->hook == f && c->hook_data == hook_data) {
8436038a 176 if(c->ref_count == 1) {
177 lttv_hooks_remove_by_position(h, i);
178 return;
179 } else {
180 g_assert(c->ref_count != 0);
181 c->ref_count--;
182 return;
183 }
dc877563 184 }
185 }
186}
187
188
189void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
190{
191 guint i, j;
192
193 LttvHookClosure *c, *c_list;
194
ffd54a90 195 if(list == NULL) return;
dc877563 196 for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
197 c = &g_array_index(h, LttvHookClosure, i);
198 c_list = &g_array_index(list, LttvHookClosure, j);
199 if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
8436038a 200 if(c->ref_count == 1) {
201 lttv_hooks_remove_by_position(h, i);
202 } else {
203 g_assert(c->ref_count != 0);
204 c->ref_count--;
205 }
dc877563 206 j++;
207 }
208 else i++;
209 }
210
211 /* Normally the hooks in h are ordered as in list. If this is not the case,
212 try harder here. */
213
214 if(j < list->len) {
215 for(; j < list->len ; j++) {
216 c_list = &g_array_index(list, LttvHookClosure, j);
217 lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
218 }
eccb5352 219 }
220}
221
222
dc877563 223unsigned lttv_hooks_number(LttvHooks *h)
224{
225 return h->len;
226}
eccb5352 227
dc877563 228
47e76340 229void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
230 LttvHookPrio *p)
dc877563 231{
232 LttvHookClosure *c;
233
47e76340 234 if(i >= h->len)
235 {
236 *f = NULL;
237 *hook_data = NULL;
238 *p = 0;
239 return;
240 }
241
dc877563 242 c = &g_array_index(h, LttvHookClosure, i);
243 *f = c->hook;
244 *hook_data = c->hook_data;
47e76340 245 *p = c->prio;
dc877563 246}
247
248
ffd54a90 249void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
dc877563 250{
ffd54a90 251 g_array_remove_index(h, i);
dc877563 252}
253
dc877563 254gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
255{
b445142a 256 gboolean ret, sum_ret = FALSE;
dc877563 257
258 LttvHookClosure *c;
259
ffd54a90 260 guint i;
261
dc877563 262 if(h != NULL) {
263 for(i = 0 ; i < h->len ; i++) {
264 c = &g_array_index(h, LttvHookClosure, i);
b445142a 265 ret = c->hook(c->hook_data,call_data);
266 sum_ret = sum_ret || ret;
dc877563 267 }
268 }
b445142a 269 return sum_ret;
dc877563 270}
271
272
273gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
274{
275 LttvHookClosure *c;
276
ffd54a90 277 guint i;
278
dc877563 279 for(i = 0 ; i < h->len ; i++) {
280 c = &g_array_index(h, LttvHookClosure, i);
281 if(c->hook(c->hook_data,call_data)) return TRUE;
282 }
283 return FALSE;
284}
285
47e76340 286gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
287 LttvHooks *h2, void *call_data2)
288{
289 gboolean ret, sum_ret = FALSE;
290
291 LttvHookClosure *c1, *c2;
292
293 guint i, j;
294
295 if(h1 != NULL && h2 != NULL) {
296 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
297 c1 = &g_array_index(h1, LttvHookClosure, i);
298 c2 = &g_array_index(h2, LttvHookClosure, j);
299 if(c1->prio <= c2->prio) {
300 ret = c1->hook(c1->hook_data,call_data1);
301 sum_ret = sum_ret || ret;
302 i++;
303 }
304 else {
305 ret = c2->hook(c2->hook_data,call_data2);
306 sum_ret = sum_ret || ret;
307 j++;
308 }
309 }
310 /* Finish the last list with hooks left */
311 for(;i < h1->len; i++) {
312 c1 = &g_array_index(h1, LttvHookClosure, i);
313 ret = c1->hook(c1->hook_data,call_data1);
314 sum_ret = sum_ret || ret;
315 }
316 for(;j < h2->len; j++) {
317 c2 = &g_array_index(h2, LttvHookClosure, j);
318 ret = c2->hook(c2->hook_data,call_data2);
319 sum_ret = sum_ret || ret;
320 }
321 }
322 else if(h1 != NULL && h2 == NULL) {
323 for(i = 0 ; i < h1->len ; i++) {
324 c1 = &g_array_index(h1, LttvHookClosure, i);
325 ret = c1->hook(c1->hook_data,call_data1);
326 sum_ret = sum_ret || ret;
327 }
328 }
329 else if(h1 == NULL && h2 != NULL) {
330 for(j = 0 ; j < h2->len ; j++) {
331 c2 = &g_array_index(h2, LttvHookClosure, j);
332 ret = c2->hook(c2->hook_data,call_data2);
333 sum_ret = sum_ret || ret;
334 }
335 }
336
337 return sum_ret;
338}
339
340gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
341 LttvHooks *h2, void *call_data2)
342{
343 LttvHookClosure *c1, *c2;
344
345 guint i, j;
346
347 if(h1 != NULL && h2 != NULL) {
348 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
349 c1 = &g_array_index(h1, LttvHookClosure, i);
350 c2 = &g_array_index(h2, LttvHookClosure, j);
351 if(c1->prio <= c2->prio) {
352 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
353 i++;
354 }
355 else {
356 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
357 j++;
358 }
359 }
360 /* Finish the last list with hooks left */
361 for(;i < h1->len; i++) {
362 c1 = &g_array_index(h1, LttvHookClosure, i);
363 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
364 }
365 for(;j < h2->len; j++) {
366 c2 = &g_array_index(h2, LttvHookClosure, j);
367 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
368 }
369 }
370 else if(h1 != NULL && h2 == NULL) {
371 for(i = 0 ; i < h1->len ; i++) {
372 c1 = &g_array_index(h1, LttvHookClosure, i);
373 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
374 }
375 }
376 else if(h1 == NULL && h2 != NULL) {
377 for(j = 0 ; j < h2->len ; j++) {
378 c2 = &g_array_index(h2, LttvHookClosure, j);
379 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
380 }
381 }
382
383 return FALSE;
384
385}
386
dc877563 387
388LttvHooksById *lttv_hooks_by_id_new()
389{
eccb5352 390 return g_ptr_array_new();
391}
392
393
dc877563 394void lttv_hooks_by_id_destroy(LttvHooksById *h)
395{
396 guint i;
397
398 for(i = 0 ; i < h->len ; i++) {
399 if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
400 }
eccb5352 401 g_ptr_array_free(h, TRUE);
402}
403
404
ffd54a90 405LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
eccb5352 406{
dc877563 407 if(h->len <= id) g_ptr_array_set_size(h, id + 1);
eccb5352 408 if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
dc877563 409 return h->pdata[id];
eccb5352 410}
411
dc877563 412
413unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
eccb5352 414{
dc877563 415 return h->len;
416}
417
418
419LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
420{
421 if(id < h->len) return h->pdata[id];
422 return NULL;
423}
424
425
426void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
427{
428 if(id < h->len && h->pdata[id] != NULL) {
429 lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
430 h->pdata[id] = NULL;
431 }
eccb5352 432}
433
This page took 0.047448 seconds and 4 git commands to generate.