Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / glib / ghook.c
blob09e888366737c1f6ed3fa34dae3fa1f50e833974
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GHook: Callback maintenance functions
5 * Copyright (C) 1998 Tim Janik
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * Modified by the GLib Team and others 1997-1999. See the AUTHORS
25 * file for a list of people on the GLib Team. See the ChangeLog
26 * files for a list of changes. These files are distributed with
27 * GLib at ftp://ftp.gtk.org/pub/gtk/.
30 /*
31 * MT safe
34 #include "glib.h"
37 /* --- defines --- */
38 #define G_HOOKS_PREALLOC (16)
41 /* --- functions --- */
42 void
43 g_hook_list_init (GHookList *hook_list,
44 guint hook_size)
46 g_return_if_fail (hook_list != NULL);
47 g_return_if_fail (hook_size >= sizeof (GHook));
49 hook_list->seq_id = 1;
50 hook_list->hook_size = hook_size;
51 hook_list->is_setup = TRUE;
52 hook_list->hooks = NULL;
53 hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk",
54 hook_size,
55 hook_size * G_HOOKS_PREALLOC,
56 G_ALLOC_AND_FREE);
57 hook_list->hook_free = NULL;
58 hook_list->hook_destroy = NULL;
61 void
62 g_hook_list_clear (GHookList *hook_list)
64 g_return_if_fail (hook_list != NULL);
66 if (hook_list->is_setup)
68 GHook *hook;
70 hook_list->is_setup = FALSE;
72 hook = hook_list->hooks;
73 if (!hook)
75 g_mem_chunk_destroy (hook_list->hook_memchunk);
76 hook_list->hook_memchunk = NULL;
78 else
81 GHook *tmp;
83 g_hook_ref (hook_list, hook);
84 g_hook_destroy_link (hook_list, hook);
85 tmp = hook->next;
86 g_hook_unref (hook_list, hook);
87 hook = tmp;
89 while (hook);
93 GHook*
94 g_hook_alloc (GHookList *hook_list)
96 GHook *hook;
98 g_return_val_if_fail (hook_list != NULL, NULL);
99 g_return_val_if_fail (hook_list->is_setup, NULL);
101 hook = g_chunk_new0 (GHook, hook_list->hook_memchunk);
102 hook->data = NULL;
103 hook->next = NULL;
104 hook->prev = NULL;
105 hook->flags = G_HOOK_FLAG_ACTIVE;
106 hook->ref_count = 0;
107 hook->hook_id = 0;
108 hook->func = NULL;
109 hook->destroy = NULL;
111 return hook;
114 void
115 g_hook_free (GHookList *hook_list,
116 GHook *hook)
118 g_return_if_fail (hook_list != NULL);
119 g_return_if_fail (hook_list->is_setup);
120 g_return_if_fail (hook != NULL);
121 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
123 if (hook_list->hook_free)
124 hook_list->hook_free (hook_list, hook);
126 g_chunk_free (hook, hook_list->hook_memchunk);
129 void
130 g_hook_destroy_link (GHookList *hook_list,
131 GHook *hook)
133 g_return_if_fail (hook_list != NULL);
134 g_return_if_fail (hook != NULL);
136 if (hook->hook_id)
138 hook->hook_id = 0;
139 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
140 if (hook_list->hook_destroy)
142 if (hook_list->hook_destroy != G_HOOK_DEFERRED_DESTROY)
143 hook_list->hook_destroy (hook_list, hook);
145 else if (hook->destroy)
147 hook->destroy (hook->data);
148 hook->data = NULL;
149 hook->func = NULL;
150 hook->destroy = NULL;
152 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
156 gboolean
157 g_hook_destroy (GHookList *hook_list,
158 guint hook_id)
160 GHook *hook;
162 g_return_val_if_fail (hook_list != NULL, FALSE);
163 g_return_val_if_fail (hook_id > 0, FALSE);
165 hook = g_hook_get (hook_list, hook_id);
166 if (hook)
168 g_hook_destroy_link (hook_list, hook);
169 return TRUE;
172 return FALSE;
175 void
176 g_hook_unref (GHookList *hook_list,
177 GHook *hook)
179 g_return_if_fail (hook_list != NULL);
180 g_return_if_fail (hook_list->hook_memchunk != NULL);
181 g_return_if_fail (hook != NULL);
182 g_return_if_fail (hook->ref_count > 0);
184 hook->ref_count--;
185 if (!hook->ref_count)
187 g_return_if_fail (hook->hook_id == 0);
188 g_return_if_fail (!G_HOOK_IN_CALL (hook));
190 if (hook->prev)
191 hook->prev->next = hook->next;
192 else
193 hook_list->hooks = hook->next;
194 if (hook->next)
196 hook->next->prev = hook->prev;
197 hook->next = NULL;
199 hook->prev = NULL;
201 if (!hook_list->is_setup)
203 hook_list->is_setup = TRUE;
204 g_hook_free (hook_list, hook);
205 hook_list->is_setup = FALSE;
207 if (!hook_list->hooks)
209 g_mem_chunk_destroy (hook_list->hook_memchunk);
210 hook_list->hook_memchunk = NULL;
213 else
214 g_hook_free (hook_list, hook);
218 void
219 g_hook_ref (GHookList *hook_list,
220 GHook *hook)
222 g_return_if_fail (hook_list != NULL);
223 g_return_if_fail (hook != NULL);
224 g_return_if_fail (hook->ref_count > 0);
226 hook->ref_count++;
229 void
230 g_hook_prepend (GHookList *hook_list,
231 GHook *hook)
233 g_return_if_fail (hook_list != NULL);
235 g_hook_insert_before (hook_list, hook_list->hooks, hook);
238 void
239 g_hook_insert_before (GHookList *hook_list,
240 GHook *sibling,
241 GHook *hook)
243 g_return_if_fail (hook_list != NULL);
244 g_return_if_fail (hook_list->is_setup);
245 g_return_if_fail (hook != NULL);
246 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
247 g_return_if_fail (hook->func != NULL);
249 hook->hook_id = hook_list->seq_id++;
250 hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
252 if (sibling)
254 if (sibling->prev)
256 hook->prev = sibling->prev;
257 hook->prev->next = hook;
258 hook->next = sibling;
259 sibling->prev = hook;
261 else
263 hook_list->hooks = hook;
264 hook->next = sibling;
265 sibling->prev = hook;
268 else
270 if (hook_list->hooks)
272 sibling = hook_list->hooks;
273 while (sibling->next)
274 sibling = sibling->next;
275 hook->prev = sibling;
276 sibling->next = hook;
278 else
279 hook_list->hooks = hook;
283 void
284 g_hook_list_invoke (GHookList *hook_list,
285 gboolean may_recurse)
287 GHook *hook;
289 g_return_if_fail (hook_list != NULL);
290 g_return_if_fail (hook_list->is_setup);
292 hook = g_hook_first_valid (hook_list, may_recurse);
293 while (hook)
295 GHookFunc func;
296 gboolean was_in_call;
298 func = (GHookFunc) hook->func;
300 was_in_call = G_HOOK_IN_CALL (hook);
301 hook->flags |= G_HOOK_FLAG_IN_CALL;
302 func (hook->data);
303 if (!was_in_call)
304 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
306 hook = g_hook_next_valid (hook_list, hook, may_recurse);
310 void
311 g_hook_list_invoke_check (GHookList *hook_list,
312 gboolean may_recurse)
314 GHook *hook;
316 g_return_if_fail (hook_list != NULL);
317 g_return_if_fail (hook_list->is_setup);
319 hook = g_hook_first_valid (hook_list, may_recurse);
320 while (hook)
322 GHookCheckFunc func;
323 gboolean was_in_call;
324 gboolean need_destroy;
326 func = (GHookCheckFunc) hook->func;
328 was_in_call = G_HOOK_IN_CALL (hook);
329 hook->flags |= G_HOOK_FLAG_IN_CALL;
330 need_destroy = !func (hook->data);
331 if (!was_in_call)
332 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
333 if (need_destroy)
334 g_hook_destroy_link (hook_list, hook);
336 hook = g_hook_next_valid (hook_list, hook, may_recurse);
340 void
341 g_hook_list_marshal_check (GHookList *hook_list,
342 gboolean may_recurse,
343 GHookCheckMarshaller marshaller,
344 gpointer data)
346 GHook *hook;
348 g_return_if_fail (hook_list != NULL);
349 g_return_if_fail (hook_list->is_setup);
350 g_return_if_fail (marshaller != NULL);
352 hook = g_hook_first_valid (hook_list, may_recurse);
353 while (hook)
355 gboolean was_in_call;
356 gboolean need_destroy;
358 was_in_call = G_HOOK_IN_CALL (hook);
359 hook->flags |= G_HOOK_FLAG_IN_CALL;
360 need_destroy = !marshaller (hook, data);
361 if (!was_in_call)
362 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
363 if (need_destroy)
364 g_hook_destroy_link (hook_list, hook);
366 hook = g_hook_next_valid (hook_list, hook, may_recurse);
370 void
371 g_hook_list_marshal (GHookList *hook_list,
372 gboolean may_recurse,
373 GHookMarshaller marshaller,
374 gpointer data)
376 GHook *hook;
378 g_return_if_fail (hook_list != NULL);
379 g_return_if_fail (hook_list->is_setup);
380 g_return_if_fail (marshaller != NULL);
382 hook = g_hook_first_valid (hook_list, may_recurse);
383 while (hook)
385 gboolean was_in_call;
387 was_in_call = G_HOOK_IN_CALL (hook);
388 hook->flags |= G_HOOK_FLAG_IN_CALL;
389 marshaller (hook, data);
390 if (!was_in_call)
391 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
393 hook = g_hook_next_valid (hook_list, hook, may_recurse);
397 GHook*
398 g_hook_first_valid (GHookList *hook_list,
399 gboolean may_be_in_call)
401 g_return_val_if_fail (hook_list != NULL, NULL);
403 if (hook_list->is_setup)
405 GHook *hook;
407 hook = hook_list->hooks;
408 if (hook)
410 g_hook_ref (hook_list, hook);
411 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
412 return hook;
413 else
414 return g_hook_next_valid (hook_list, hook, may_be_in_call);
418 return NULL;
421 GHook*
422 g_hook_next_valid (GHookList *hook_list,
423 GHook *hook,
424 gboolean may_be_in_call)
426 GHook *ohook = hook;
428 g_return_val_if_fail (hook_list != NULL, NULL);
430 if (!hook)
431 return NULL;
433 hook = hook->next;
434 while (hook)
436 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
438 g_hook_ref (hook_list, hook);
439 g_hook_unref (hook_list, ohook);
441 return hook;
443 hook = hook->next;
445 g_hook_unref (hook_list, ohook);
447 return NULL;
450 GHook*
451 g_hook_get (GHookList *hook_list,
452 guint hook_id)
454 GHook *hook;
456 g_return_val_if_fail (hook_list != NULL, NULL);
457 g_return_val_if_fail (hook_id > 0, NULL);
459 hook = hook_list->hooks;
460 while (hook)
462 if (hook->hook_id == hook_id)
463 return hook;
464 hook = hook->next;
467 return NULL;
470 GHook*
471 g_hook_find (GHookList *hook_list,
472 gboolean need_valids,
473 GHookFindFunc func,
474 gpointer data)
476 GHook *hook;
478 g_return_val_if_fail (hook_list != NULL, NULL);
479 g_return_val_if_fail (func != NULL, NULL);
481 hook = hook_list->hooks;
482 while (hook)
484 GHook *tmp;
486 /* test only non-destroyed hooks */
487 if (!hook->hook_id)
489 hook = hook->next;
490 continue;
493 g_hook_ref (hook_list, hook);
495 if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
497 g_hook_unref (hook_list, hook);
499 return hook;
502 tmp = hook->next;
503 g_hook_unref (hook_list, hook);
504 hook = tmp;
507 return NULL;
510 GHook*
511 g_hook_find_data (GHookList *hook_list,
512 gboolean need_valids,
513 gpointer data)
515 GHook *hook;
517 g_return_val_if_fail (hook_list != NULL, NULL);
519 hook = hook_list->hooks;
520 while (hook)
522 /* test only non-destroyed hooks */
523 if (hook->data == data &&
524 hook->hook_id &&
525 (!need_valids || G_HOOK_ACTIVE (hook)))
526 return hook;
528 hook = hook->next;
531 return NULL;
534 GHook*
535 g_hook_find_func (GHookList *hook_list,
536 gboolean need_valids,
537 gpointer func)
539 GHook *hook;
541 g_return_val_if_fail (hook_list != NULL, NULL);
542 g_return_val_if_fail (func != NULL, NULL);
544 hook = hook_list->hooks;
545 while (hook)
547 /* test only non-destroyed hooks */
548 if (hook->func == func &&
549 hook->hook_id &&
550 (!need_valids || G_HOOK_ACTIVE (hook)))
551 return hook;
553 hook = hook->next;
556 return NULL;
559 GHook*
560 g_hook_find_func_data (GHookList *hook_list,
561 gboolean need_valids,
562 gpointer func,
563 gpointer data)
565 GHook *hook;
567 g_return_val_if_fail (hook_list != NULL, NULL);
568 g_return_val_if_fail (func != NULL, NULL);
570 hook = hook_list->hooks;
571 while (hook)
573 /* test only non-destroyed hooks */
574 if (hook->data == data &&
575 hook->func == func &&
576 hook->hook_id &&
577 (!need_valids || G_HOOK_ACTIVE (hook)))
578 return hook;
580 hook = hook->next;
583 return NULL;
586 void
587 g_hook_insert_sorted (GHookList *hook_list,
588 GHook *hook,
589 GHookCompareFunc func)
591 GHook *sibling;
593 g_return_if_fail (hook_list != NULL);
594 g_return_if_fail (hook_list->is_setup);
595 g_return_if_fail (hook != NULL);
596 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
597 g_return_if_fail (hook->func != NULL);
598 g_return_if_fail (func != NULL);
600 /* first non-destroyed hook */
601 sibling = hook_list->hooks;
602 while (sibling && !sibling->hook_id)
603 sibling = sibling->next;
605 while (sibling)
607 GHook *tmp;
609 g_hook_ref (hook_list, sibling);
610 if (func (hook, sibling) <= 0 && sibling->hook_id)
612 g_hook_unref (hook_list, sibling);
613 break;
616 /* next non-destroyed hook */
617 tmp = sibling->next;
618 while (tmp && !tmp->hook_id)
619 tmp = tmp->next;
621 g_hook_unref (hook_list, sibling);
622 sibling = tmp;
625 g_hook_insert_before (hook_list, sibling, hook);
628 gint
629 g_hook_compare_ids (GHook *new_hook,
630 GHook *sibling)
632 return ((glong) new_hook->hook_id) - ((glong) sibling->hook_id);