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 Lesser 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 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser 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-2000. 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/.
40 /* --- functions --- */
42 default_finalize_hook (GHookList *hook_list,
45 GDestroyNotify destroy = hook->destroy;
55 g_hook_list_init (GHookList *hook_list,
58 g_return_if_fail (hook_list != NULL);
59 g_return_if_fail (hook_size >= sizeof (GHook));
61 hook_list->seq_id = 1;
62 hook_list->hook_size = hook_size;
63 hook_list->is_setup = TRUE;
64 hook_list->hooks = NULL;
65 hook_list->dummy3 = NULL;
66 hook_list->finalize_hook = default_finalize_hook;
67 hook_list->dummy[0] = NULL;
68 hook_list->dummy[1] = NULL;
72 g_hook_list_clear (GHookList *hook_list)
74 g_return_if_fail (hook_list != NULL);
76 if (hook_list->is_setup)
80 hook_list->is_setup = FALSE;
82 hook = hook_list->hooks;
85 /* destroy hook_list->hook_memchunk */
92 g_hook_ref (hook_list, hook);
93 g_hook_destroy_link (hook_list, hook);
95 g_hook_unref (hook_list, hook);
103 g_hook_alloc (GHookList *hook_list)
107 g_return_val_if_fail (hook_list != NULL, NULL);
108 g_return_val_if_fail (hook_list->is_setup, NULL);
110 hook = g_slice_alloc0 (hook_list->hook_size);
114 hook->flags = G_HOOK_FLAG_ACTIVE;
118 hook->destroy = NULL;
124 g_hook_free (GHookList *hook_list,
127 g_return_if_fail (hook_list != NULL);
128 g_return_if_fail (hook_list->is_setup);
129 g_return_if_fail (hook != NULL);
130 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
131 g_return_if_fail (!G_HOOK_IN_CALL (hook));
133 hook_list->finalize_hook (hook_list, hook);
134 g_slice_free1 (hook_list->hook_size, hook);
138 g_hook_destroy_link (GHookList *hook_list,
141 g_return_if_fail (hook_list != NULL);
142 g_return_if_fail (hook != NULL);
144 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
148 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
153 g_hook_destroy (GHookList *hook_list,
158 g_return_val_if_fail (hook_list != NULL, FALSE);
159 g_return_val_if_fail (hook_id > 0, FALSE);
161 hook = g_hook_get (hook_list, hook_id);
164 g_hook_destroy_link (hook_list, hook);
172 g_hook_unref (GHookList *hook_list,
175 g_return_if_fail (hook_list != NULL);
176 g_return_if_fail (hook != NULL);
177 g_return_if_fail (hook->ref_count > 0);
180 if (!hook->ref_count)
182 g_return_if_fail (hook->hook_id == 0);
183 g_return_if_fail (!G_HOOK_IN_CALL (hook));
186 hook->prev->next = hook->next;
188 hook_list->hooks = hook->next;
191 hook->next->prev = hook->prev;
196 if (!hook_list->is_setup)
198 hook_list->is_setup = TRUE;
199 g_hook_free (hook_list, hook);
200 hook_list->is_setup = FALSE;
202 if (!hook_list->hooks)
204 /* destroy hook_list->hook_memchunk */
208 g_hook_free (hook_list, hook);
213 g_hook_ref (GHookList *hook_list,
216 g_return_val_if_fail (hook_list != NULL, NULL);
217 g_return_val_if_fail (hook != NULL, NULL);
218 g_return_val_if_fail (hook->ref_count > 0, NULL);
226 g_hook_prepend (GHookList *hook_list,
229 g_return_if_fail (hook_list != NULL);
231 g_hook_insert_before (hook_list, hook_list->hooks, hook);
235 g_hook_insert_before (GHookList *hook_list,
239 g_return_if_fail (hook_list != NULL);
240 g_return_if_fail (hook_list->is_setup);
241 g_return_if_fail (hook != NULL);
242 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
243 g_return_if_fail (hook->ref_count == 0);
245 hook->hook_id = hook_list->seq_id++;
246 hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
252 hook->prev = sibling->prev;
253 hook->prev->next = hook;
254 hook->next = sibling;
255 sibling->prev = hook;
259 hook_list->hooks = hook;
260 hook->next = sibling;
261 sibling->prev = hook;
266 if (hook_list->hooks)
268 sibling = hook_list->hooks;
269 while (sibling->next)
270 sibling = sibling->next;
271 hook->prev = sibling;
272 sibling->next = hook;
275 hook_list->hooks = hook;
280 g_hook_list_invoke (GHookList *hook_list,
281 gboolean may_recurse)
285 g_return_if_fail (hook_list != NULL);
286 g_return_if_fail (hook_list->is_setup);
288 hook = g_hook_first_valid (hook_list, may_recurse);
292 gboolean was_in_call;
294 func = (GHookFunc) hook->func;
296 was_in_call = G_HOOK_IN_CALL (hook);
297 hook->flags |= G_HOOK_FLAG_IN_CALL;
300 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
302 hook = g_hook_next_valid (hook_list, hook, may_recurse);
307 g_hook_list_invoke_check (GHookList *hook_list,
308 gboolean may_recurse)
312 g_return_if_fail (hook_list != NULL);
313 g_return_if_fail (hook_list->is_setup);
315 hook = g_hook_first_valid (hook_list, may_recurse);
319 gboolean was_in_call;
320 gboolean need_destroy;
322 func = (GHookCheckFunc) hook->func;
324 was_in_call = G_HOOK_IN_CALL (hook);
325 hook->flags |= G_HOOK_FLAG_IN_CALL;
326 need_destroy = !func (hook->data);
328 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
330 g_hook_destroy_link (hook_list, hook);
332 hook = g_hook_next_valid (hook_list, hook, may_recurse);
337 g_hook_list_marshal_check (GHookList *hook_list,
338 gboolean may_recurse,
339 GHookCheckMarshaller marshaller,
344 g_return_if_fail (hook_list != NULL);
345 g_return_if_fail (hook_list->is_setup);
346 g_return_if_fail (marshaller != NULL);
348 hook = g_hook_first_valid (hook_list, may_recurse);
351 gboolean was_in_call;
352 gboolean need_destroy;
354 was_in_call = G_HOOK_IN_CALL (hook);
355 hook->flags |= G_HOOK_FLAG_IN_CALL;
356 need_destroy = !marshaller (hook, data);
358 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
360 g_hook_destroy_link (hook_list, hook);
362 hook = g_hook_next_valid (hook_list, hook, may_recurse);
367 g_hook_list_marshal (GHookList *hook_list,
368 gboolean may_recurse,
369 GHookMarshaller marshaller,
374 g_return_if_fail (hook_list != NULL);
375 g_return_if_fail (hook_list->is_setup);
376 g_return_if_fail (marshaller != NULL);
378 hook = g_hook_first_valid (hook_list, may_recurse);
381 gboolean was_in_call;
383 was_in_call = G_HOOK_IN_CALL (hook);
384 hook->flags |= G_HOOK_FLAG_IN_CALL;
385 marshaller (hook, data);
387 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
389 hook = g_hook_next_valid (hook_list, hook, may_recurse);
394 g_hook_first_valid (GHookList *hook_list,
395 gboolean may_be_in_call)
397 g_return_val_if_fail (hook_list != NULL, NULL);
399 if (hook_list->is_setup)
403 hook = hook_list->hooks;
406 g_hook_ref (hook_list, hook);
407 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
410 return g_hook_next_valid (hook_list, hook, may_be_in_call);
418 g_hook_next_valid (GHookList *hook_list,
420 gboolean may_be_in_call)
424 g_return_val_if_fail (hook_list != NULL, NULL);
432 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
434 g_hook_ref (hook_list, hook);
435 g_hook_unref (hook_list, ohook);
441 g_hook_unref (hook_list, ohook);
447 g_hook_get (GHookList *hook_list,
452 g_return_val_if_fail (hook_list != NULL, NULL);
453 g_return_val_if_fail (hook_id > 0, NULL);
455 hook = hook_list->hooks;
458 if (hook->hook_id == hook_id)
467 g_hook_find (GHookList *hook_list,
468 gboolean need_valids,
474 g_return_val_if_fail (hook_list != NULL, NULL);
475 g_return_val_if_fail (func != NULL, NULL);
477 hook = hook_list->hooks;
482 /* test only non-destroyed hooks */
489 g_hook_ref (hook_list, hook);
491 if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
493 g_hook_unref (hook_list, hook);
499 g_hook_unref (hook_list, hook);
507 g_hook_find_data (GHookList *hook_list,
508 gboolean need_valids,
513 g_return_val_if_fail (hook_list != NULL, NULL);
515 hook = hook_list->hooks;
518 /* test only non-destroyed hooks */
519 if (hook->data == data &&
521 (!need_valids || G_HOOK_ACTIVE (hook)))
531 g_hook_find_func (GHookList *hook_list,
532 gboolean need_valids,
537 g_return_val_if_fail (hook_list != NULL, NULL);
538 g_return_val_if_fail (func != NULL, NULL);
540 hook = hook_list->hooks;
543 /* test only non-destroyed hooks */
544 if (hook->func == func &&
546 (!need_valids || G_HOOK_ACTIVE (hook)))
556 g_hook_find_func_data (GHookList *hook_list,
557 gboolean need_valids,
563 g_return_val_if_fail (hook_list != NULL, NULL);
564 g_return_val_if_fail (func != NULL, NULL);
566 hook = hook_list->hooks;
569 /* test only non-destroyed hooks */
570 if (hook->data == data &&
571 hook->func == func &&
573 (!need_valids || G_HOOK_ACTIVE (hook)))
583 g_hook_insert_sorted (GHookList *hook_list,
585 GHookCompareFunc func)
589 g_return_if_fail (hook_list != NULL);
590 g_return_if_fail (hook_list->is_setup);
591 g_return_if_fail (hook != NULL);
592 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
593 g_return_if_fail (hook->func != NULL);
594 g_return_if_fail (func != NULL);
596 /* first non-destroyed hook */
597 sibling = hook_list->hooks;
598 while (sibling && !sibling->hook_id)
599 sibling = sibling->next;
605 g_hook_ref (hook_list, sibling);
606 if (func (hook, sibling) <= 0 && sibling->hook_id)
608 g_hook_unref (hook_list, sibling);
612 /* next non-destroyed hook */
614 while (tmp && !tmp->hook_id)
617 g_hook_unref (hook_list, sibling);
621 g_hook_insert_before (hook_list, sibling, hook);
625 g_hook_compare_ids (GHook *new_hook,
628 if (new_hook->hook_id < sibling->hook_id)
630 else if (new_hook->hook_id > sibling->hook_id)
637 #include "galiasdef.c"