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/.
38 #include "gtestutils.h"
42 /* --- functions --- */
44 default_finalize_hook (GHookList *hook_list,
47 GDestroyNotify destroy = hook->destroy;
57 g_hook_list_init (GHookList *hook_list,
60 g_return_if_fail (hook_list != NULL);
61 g_return_if_fail (hook_size >= sizeof (GHook));
63 hook_list->seq_id = 1;
64 hook_list->hook_size = hook_size;
65 hook_list->is_setup = TRUE;
66 hook_list->hooks = NULL;
67 hook_list->dummy3 = NULL;
68 hook_list->finalize_hook = default_finalize_hook;
69 hook_list->dummy[0] = NULL;
70 hook_list->dummy[1] = NULL;
74 g_hook_list_clear (GHookList *hook_list)
76 g_return_if_fail (hook_list != NULL);
78 if (hook_list->is_setup)
82 hook_list->is_setup = FALSE;
84 hook = hook_list->hooks;
87 /* destroy hook_list->hook_memchunk */
94 g_hook_ref (hook_list, hook);
95 g_hook_destroy_link (hook_list, hook);
97 g_hook_unref (hook_list, hook);
105 g_hook_alloc (GHookList *hook_list)
109 g_return_val_if_fail (hook_list != NULL, NULL);
110 g_return_val_if_fail (hook_list->is_setup, NULL);
112 hook = g_slice_alloc0 (hook_list->hook_size);
116 hook->flags = G_HOOK_FLAG_ACTIVE;
120 hook->destroy = NULL;
126 g_hook_free (GHookList *hook_list,
129 g_return_if_fail (hook_list != NULL);
130 g_return_if_fail (hook_list->is_setup);
131 g_return_if_fail (hook != NULL);
132 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
133 g_return_if_fail (!G_HOOK_IN_CALL (hook));
135 if(hook_list->finalize_hook != NULL)
136 hook_list->finalize_hook (hook_list, hook);
137 g_slice_free1 (hook_list->hook_size, hook);
141 g_hook_destroy_link (GHookList *hook_list,
144 g_return_if_fail (hook_list != NULL);
145 g_return_if_fail (hook != NULL);
147 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
151 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
156 g_hook_destroy (GHookList *hook_list,
161 g_return_val_if_fail (hook_list != NULL, FALSE);
162 g_return_val_if_fail (hook_id > 0, FALSE);
164 hook = g_hook_get (hook_list, hook_id);
167 g_hook_destroy_link (hook_list, hook);
175 g_hook_unref (GHookList *hook_list,
178 g_return_if_fail (hook_list != NULL);
179 g_return_if_fail (hook != NULL);
180 g_return_if_fail (hook->ref_count > 0);
183 if (!hook->ref_count)
185 g_return_if_fail (hook->hook_id == 0);
186 g_return_if_fail (!G_HOOK_IN_CALL (hook));
189 hook->prev->next = hook->next;
191 hook_list->hooks = hook->next;
194 hook->next->prev = hook->prev;
199 if (!hook_list->is_setup)
201 hook_list->is_setup = TRUE;
202 g_hook_free (hook_list, hook);
203 hook_list->is_setup = FALSE;
205 if (!hook_list->hooks)
207 /* destroy hook_list->hook_memchunk */
211 g_hook_free (hook_list, hook);
216 g_hook_ref (GHookList *hook_list,
219 g_return_val_if_fail (hook_list != NULL, NULL);
220 g_return_val_if_fail (hook != NULL, NULL);
221 g_return_val_if_fail (hook->ref_count > 0, NULL);
229 g_hook_prepend (GHookList *hook_list,
232 g_return_if_fail (hook_list != NULL);
234 g_hook_insert_before (hook_list, hook_list->hooks, hook);
238 g_hook_insert_before (GHookList *hook_list,
242 g_return_if_fail (hook_list != NULL);
243 g_return_if_fail (hook_list->is_setup);
244 g_return_if_fail (hook != NULL);
245 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
246 g_return_if_fail (hook->ref_count == 0);
248 hook->hook_id = hook_list->seq_id++;
249 hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
255 hook->prev = sibling->prev;
256 hook->prev->next = hook;
257 hook->next = sibling;
258 sibling->prev = hook;
262 hook_list->hooks = hook;
263 hook->next = sibling;
264 sibling->prev = hook;
269 if (hook_list->hooks)
271 sibling = hook_list->hooks;
272 while (sibling->next)
273 sibling = sibling->next;
274 hook->prev = sibling;
275 sibling->next = hook;
278 hook_list->hooks = hook;
283 g_hook_list_invoke (GHookList *hook_list,
284 gboolean may_recurse)
288 g_return_if_fail (hook_list != NULL);
289 g_return_if_fail (hook_list->is_setup);
291 hook = g_hook_first_valid (hook_list, may_recurse);
295 gboolean was_in_call;
297 func = (GHookFunc) hook->func;
299 was_in_call = G_HOOK_IN_CALL (hook);
300 hook->flags |= G_HOOK_FLAG_IN_CALL;
303 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
305 hook = g_hook_next_valid (hook_list, hook, may_recurse);
310 g_hook_list_invoke_check (GHookList *hook_list,
311 gboolean may_recurse)
315 g_return_if_fail (hook_list != NULL);
316 g_return_if_fail (hook_list->is_setup);
318 hook = g_hook_first_valid (hook_list, may_recurse);
322 gboolean was_in_call;
323 gboolean need_destroy;
325 func = (GHookCheckFunc) hook->func;
327 was_in_call = G_HOOK_IN_CALL (hook);
328 hook->flags |= G_HOOK_FLAG_IN_CALL;
329 need_destroy = !func (hook->data);
331 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
333 g_hook_destroy_link (hook_list, hook);
335 hook = g_hook_next_valid (hook_list, hook, may_recurse);
340 g_hook_list_marshal_check (GHookList *hook_list,
341 gboolean may_recurse,
342 GHookCheckMarshaller marshaller,
347 g_return_if_fail (hook_list != NULL);
348 g_return_if_fail (hook_list->is_setup);
349 g_return_if_fail (marshaller != NULL);
351 hook = g_hook_first_valid (hook_list, may_recurse);
354 gboolean was_in_call;
355 gboolean need_destroy;
357 was_in_call = G_HOOK_IN_CALL (hook);
358 hook->flags |= G_HOOK_FLAG_IN_CALL;
359 need_destroy = !marshaller (hook, data);
361 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
363 g_hook_destroy_link (hook_list, hook);
365 hook = g_hook_next_valid (hook_list, hook, may_recurse);
370 g_hook_list_marshal (GHookList *hook_list,
371 gboolean may_recurse,
372 GHookMarshaller marshaller,
377 g_return_if_fail (hook_list != NULL);
378 g_return_if_fail (hook_list->is_setup);
379 g_return_if_fail (marshaller != NULL);
381 hook = g_hook_first_valid (hook_list, may_recurse);
384 gboolean was_in_call;
386 was_in_call = G_HOOK_IN_CALL (hook);
387 hook->flags |= G_HOOK_FLAG_IN_CALL;
388 marshaller (hook, data);
390 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
392 hook = g_hook_next_valid (hook_list, hook, may_recurse);
397 g_hook_first_valid (GHookList *hook_list,
398 gboolean may_be_in_call)
400 g_return_val_if_fail (hook_list != NULL, NULL);
402 if (hook_list->is_setup)
406 hook = hook_list->hooks;
409 g_hook_ref (hook_list, hook);
410 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
413 return g_hook_next_valid (hook_list, hook, may_be_in_call);
421 g_hook_next_valid (GHookList *hook_list,
423 gboolean may_be_in_call)
427 g_return_val_if_fail (hook_list != NULL, NULL);
435 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
437 g_hook_ref (hook_list, hook);
438 g_hook_unref (hook_list, ohook);
444 g_hook_unref (hook_list, ohook);
450 g_hook_get (GHookList *hook_list,
455 g_return_val_if_fail (hook_list != NULL, NULL);
456 g_return_val_if_fail (hook_id > 0, NULL);
458 hook = hook_list->hooks;
461 if (hook->hook_id == hook_id)
470 g_hook_find (GHookList *hook_list,
471 gboolean need_valids,
477 g_return_val_if_fail (hook_list != NULL, NULL);
478 g_return_val_if_fail (func != NULL, NULL);
480 hook = hook_list->hooks;
485 /* test only non-destroyed hooks */
492 g_hook_ref (hook_list, hook);
494 if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
496 g_hook_unref (hook_list, hook);
502 g_hook_unref (hook_list, hook);
510 g_hook_find_data (GHookList *hook_list,
511 gboolean need_valids,
516 g_return_val_if_fail (hook_list != NULL, NULL);
518 hook = hook_list->hooks;
521 /* test only non-destroyed hooks */
522 if (hook->data == data &&
524 (!need_valids || G_HOOK_ACTIVE (hook)))
534 g_hook_find_func (GHookList *hook_list,
535 gboolean need_valids,
540 g_return_val_if_fail (hook_list != NULL, NULL);
541 g_return_val_if_fail (func != NULL, NULL);
543 hook = hook_list->hooks;
546 /* test only non-destroyed hooks */
547 if (hook->func == func &&
549 (!need_valids || G_HOOK_ACTIVE (hook)))
559 g_hook_find_func_data (GHookList *hook_list,
560 gboolean need_valids,
566 g_return_val_if_fail (hook_list != NULL, NULL);
567 g_return_val_if_fail (func != NULL, NULL);
569 hook = hook_list->hooks;
572 /* test only non-destroyed hooks */
573 if (hook->data == data &&
574 hook->func == func &&
576 (!need_valids || G_HOOK_ACTIVE (hook)))
586 g_hook_insert_sorted (GHookList *hook_list,
588 GHookCompareFunc func)
592 g_return_if_fail (hook_list != NULL);
593 g_return_if_fail (hook_list->is_setup);
594 g_return_if_fail (hook != NULL);
595 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
596 g_return_if_fail (hook->func != NULL);
597 g_return_if_fail (func != NULL);
599 /* first non-destroyed hook */
600 sibling = hook_list->hooks;
601 while (sibling && !sibling->hook_id)
602 sibling = sibling->next;
608 g_hook_ref (hook_list, sibling);
609 if (func (hook, sibling) <= 0 && sibling->hook_id)
611 g_hook_unref (hook_list, sibling);
615 /* next non-destroyed hook */
617 while (tmp && !tmp->hook_id)
620 g_hook_unref (hook_list, sibling);
624 g_hook_insert_before (hook_list, sibling, hook);
628 g_hook_compare_ids (GHook *new_hook,
631 if (new_hook->hook_id < sibling->hook_id)
633 else if (new_hook->hook_id > sibling->hook_id)