Make --enable-man and --enable-gtk-doc independent
[glib.git] / glib / ghook.c
blob93ea846bceba0cb55f9c33735e401c4a5bbc8baa
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/.
31 * MT safe
34 #include "config.h"
36 #include "ghook.h"
38 #include "gtestutils.h"
39 #include "gslice.h"
41 /**
42 * SECTION:hooks
43 * @title: Hook Functions
44 * @short_description: support for manipulating lists of hook functions
46 * The #GHookList, #GHook and their related functions provide support for
47 * lists of hook functions. Functions can be added and removed from the lists,
48 * and the list of hook functions can be invoked.
51 /**
52 * GHookList:
53 * @seq_id: the next free #GHook id
54 * @hook_size: the size of the #GHookList elements, in bytes
55 * @is_setup: 1 if the #GHookList has been initialized
56 * @hooks: the first #GHook element in the list
57 * @dummy3: unused
58 * @finalize_hook: the function to call to finalize a #GHook element.
59 * The default behaviour is to call the hooks @destroy function
60 * @dummy: unused
62 * The <structname>GHookList</structname> struct represents a
63 * list of hook functions.
66 /**
67 * GHookFinalizeFunc:
68 * @hook_list: a #GHookList
69 * @hook: the hook in @hook_list that gets finalized
71 * Defines the type of function to be called when a hook in a
72 * list of hooks gets finalized.
75 /**
76 * GHookFlagMask:
77 * @G_HOOK_FLAG_ACTIVE: set if the hook has not been destroyed
78 * @G_HOOK_FLAG_IN_CALL: set if the hook is currently being run
79 * @G_HOOK_FLAG_MASK: A mask covering all bits reserved for
80 * hook flags; see %G_HOOK_FLAG_USER_SHIFT
82 * Flags used internally in the #GHook implementation.
85 /**
86 * G_HOOK_FLAGS:
87 * @hook: a #GHook
89 * Gets the flags of a hook.
92 /**
93 * G_HOOK_FLAG_USER_SHIFT:
95 * The position of the first bit which is not reserved for internal
96 * use be the #GHook implementation, i.e.
97 * <literal>1 &lt;&lt; G_HOOK_FLAG_USER_SHIFT</literal> is the first
98 * bit which can be used for application-defined flags.
102 * G_HOOK:
103 * @hook: a pointer
105 * Casts a pointer to a <literal>GHook*</literal>.
109 * G_HOOK_IS_VALID:
110 * @hook: a #GHook
112 * Returns %TRUE if the #GHook is valid, i.e. it is in a #GHookList,
113 * it is active and it has not been destroyed.
115 * Returns: %TRUE if the #GHook is valid
119 * G_HOOK_ACTIVE:
120 * @hook: a #GHook
122 * Returns %TRUE if the #GHook is active, which is normally the case
123 * until the #GHook is destroyed.
125 * Returns: %TRUE if the #GHook is active
129 * G_HOOK_IN_CALL:
130 * @hook: a #GHook
132 * Returns %TRUE if the #GHook function is currently executing.
134 * Returns: %TRUE if the #GHook function is currently executing
138 * G_HOOK_IS_UNLINKED:
139 * @hook: a #GHook
141 * Returns %TRUE if the #GHook is not in a #GHookList.
143 * Returns: %TRUE if the #GHook is not in a #GHookList
147 * GHook:
148 * @data: data which is passed to func when this hook is invoked
149 * @next: pointer to the next hook in the list
150 * @prev: pointer to the previous hook in the list
151 * @ref_count: the reference count of this hook
152 * @hook_id: the id of this hook, which is unique within its list
153 * @flags: flags which are set for this hook. See #GHookFlagMask for
154 * predefined flags
155 * @func: the function to call when this hook is invoked. The possible
156 * signatures for this function are #GHookFunc and #GHookCheckFunc
157 * @destroy: the default @finalize_hook function of a #GHookList calls
158 * this member of the hook that is being finalized
160 * The <structname>GHook</structname> struct represents a single hook
161 * function in a #GHookList.
165 * GHookFunc:
166 * @data: the data field of the #GHook is passed to the hook function here
168 * Defines the type of a hook function that can be invoked
169 * by g_hook_list_invoke().
173 * GHookCheckFunc:
174 * @data: the data field of the #GHook is passed to the hook function here
176 * Defines the type of a hook function that can be invoked
177 * by g_hook_list_invoke_check().
179 * Returns: %FALSE if the #GHook should be destroyed
182 /* --- functions --- */
183 static void
184 default_finalize_hook (GHookList *hook_list,
185 GHook *hook)
187 GDestroyNotify destroy = hook->destroy;
189 if (destroy)
191 hook->destroy = NULL;
192 destroy (hook->data);
197 * g_hook_list_init:
198 * @hook_list: a #GHookList
199 * @hook_size: the size of each element in the #GHookList,
200 * typically <literal>sizeof (GHook)</literal>
202 * Initializes a #GHookList.
203 * This must be called before the #GHookList is used.
205 void
206 g_hook_list_init (GHookList *hook_list,
207 guint hook_size)
209 g_return_if_fail (hook_list != NULL);
210 g_return_if_fail (hook_size >= sizeof (GHook));
212 hook_list->seq_id = 1;
213 hook_list->hook_size = hook_size;
214 hook_list->is_setup = TRUE;
215 hook_list->hooks = NULL;
216 hook_list->dummy3 = NULL;
217 hook_list->finalize_hook = default_finalize_hook;
218 hook_list->dummy[0] = NULL;
219 hook_list->dummy[1] = NULL;
223 * g_hook_list_clear:
224 * @hook_list: a #GHookList
226 * Removes all the #GHook elements from a #GHookList.
228 void
229 g_hook_list_clear (GHookList *hook_list)
231 g_return_if_fail (hook_list != NULL);
233 if (hook_list->is_setup)
235 GHook *hook;
237 hook_list->is_setup = FALSE;
239 hook = hook_list->hooks;
240 if (!hook)
242 /* destroy hook_list->hook_memchunk */
244 else
247 GHook *tmp;
249 g_hook_ref (hook_list, hook);
250 g_hook_destroy_link (hook_list, hook);
251 tmp = hook->next;
252 g_hook_unref (hook_list, hook);
253 hook = tmp;
255 while (hook);
260 * g_hook_alloc:
261 * @hook_list: a #GHookList
263 * Allocates space for a #GHook and initializes it.
265 * Returns: a new #GHook
267 GHook*
268 g_hook_alloc (GHookList *hook_list)
270 GHook *hook;
272 g_return_val_if_fail (hook_list != NULL, NULL);
273 g_return_val_if_fail (hook_list->is_setup, NULL);
275 hook = g_slice_alloc0 (hook_list->hook_size);
276 hook->data = NULL;
277 hook->next = NULL;
278 hook->prev = NULL;
279 hook->flags = G_HOOK_FLAG_ACTIVE;
280 hook->ref_count = 0;
281 hook->hook_id = 0;
282 hook->func = NULL;
283 hook->destroy = NULL;
285 return hook;
288 * g_hook_free:
289 * @hook_list: a #GHookList
290 * @hook: the #GHook to free
292 * Calls the #GHookList @finalize_hook function if it exists,
293 * and frees the memory allocated for the #GHook.
295 void
296 g_hook_free (GHookList *hook_list,
297 GHook *hook)
299 g_return_if_fail (hook_list != NULL);
300 g_return_if_fail (hook_list->is_setup);
301 g_return_if_fail (hook != NULL);
302 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
303 g_return_if_fail (!G_HOOK_IN_CALL (hook));
305 if(hook_list->finalize_hook != NULL)
306 hook_list->finalize_hook (hook_list, hook);
307 g_slice_free1 (hook_list->hook_size, hook);
311 * g_hook_destroy_link:
312 * @hook_list: a #GHookList
313 * @hook: the #GHook to remove
315 * Removes one #GHook from a #GHookList, marking it
316 * inactive and calling g_hook_unref() on it.
318 void
319 g_hook_destroy_link (GHookList *hook_list,
320 GHook *hook)
322 g_return_if_fail (hook_list != NULL);
323 g_return_if_fail (hook != NULL);
325 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
326 if (hook->hook_id)
328 hook->hook_id = 0;
329 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
334 * g_hook_destroy:
335 * @hook_list: a #GHookList
336 * @hook_id: a hook ID
338 * Destroys a #GHook, given its ID.
340 * Returns: %TRUE if the #GHook was found in the #GHookList and destroyed
342 gboolean
343 g_hook_destroy (GHookList *hook_list,
344 gulong hook_id)
346 GHook *hook;
348 g_return_val_if_fail (hook_list != NULL, FALSE);
349 g_return_val_if_fail (hook_id > 0, FALSE);
351 hook = g_hook_get (hook_list, hook_id);
352 if (hook)
354 g_hook_destroy_link (hook_list, hook);
355 return TRUE;
358 return FALSE;
362 * g_hook_unref:
363 * @hook_list: a #GHookList
364 * @hook: the #GHook to unref
366 * Decrements the reference count of a #GHook.
367 * If the reference count falls to 0, the #GHook is removed
368 * from the #GHookList and g_hook_free() is called to free it.
370 void
371 g_hook_unref (GHookList *hook_list,
372 GHook *hook)
374 g_return_if_fail (hook_list != NULL);
375 g_return_if_fail (hook != NULL);
376 g_return_if_fail (hook->ref_count > 0);
378 hook->ref_count--;
379 if (!hook->ref_count)
381 g_return_if_fail (hook->hook_id == 0);
382 g_return_if_fail (!G_HOOK_IN_CALL (hook));
384 if (hook->prev)
385 hook->prev->next = hook->next;
386 else
387 hook_list->hooks = hook->next;
388 if (hook->next)
390 hook->next->prev = hook->prev;
391 hook->next = NULL;
393 hook->prev = NULL;
395 if (!hook_list->is_setup)
397 hook_list->is_setup = TRUE;
398 g_hook_free (hook_list, hook);
399 hook_list->is_setup = FALSE;
401 if (!hook_list->hooks)
403 /* destroy hook_list->hook_memchunk */
406 else
407 g_hook_free (hook_list, hook);
412 * g_hook_ref:
413 * @hook_list: a #GHookList
414 * @hook: the #GHook to increment the reference count of
416 * Increments the reference count for a #GHook.
418 * Returns: the @hook that was passed in (since 2.6)
420 GHook *
421 g_hook_ref (GHookList *hook_list,
422 GHook *hook)
424 g_return_val_if_fail (hook_list != NULL, NULL);
425 g_return_val_if_fail (hook != NULL, NULL);
426 g_return_val_if_fail (hook->ref_count > 0, NULL);
428 hook->ref_count++;
430 return hook;
434 * g_hook_append:
435 * @hook_list: a #GHookList
436 * @hook: the #GHook to add to the end of @hook_list
438 * Appends a #GHook onto the end of a #GHookList.
442 * g_hook_prepend:
443 * @hook_list: a #GHookList
444 * @hook: the #GHook to add to the start of @hook_list
446 * Prepends a #GHook on the start of a #GHookList.
448 void
449 g_hook_prepend (GHookList *hook_list,
450 GHook *hook)
452 g_return_if_fail (hook_list != NULL);
454 g_hook_insert_before (hook_list, hook_list->hooks, hook);
458 * g_hook_insert_before:
459 * @hook_list: a #GHookList
460 * @sibling: the #GHook to insert the new #GHook before
461 * @hook: the #GHook to insert
463 * Inserts a #GHook into a #GHookList, before a given #GHook.
465 void
466 g_hook_insert_before (GHookList *hook_list,
467 GHook *sibling,
468 GHook *hook)
470 g_return_if_fail (hook_list != NULL);
471 g_return_if_fail (hook_list->is_setup);
472 g_return_if_fail (hook != NULL);
473 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
474 g_return_if_fail (hook->ref_count == 0);
476 hook->hook_id = hook_list->seq_id++;
477 hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
479 if (sibling)
481 if (sibling->prev)
483 hook->prev = sibling->prev;
484 hook->prev->next = hook;
485 hook->next = sibling;
486 sibling->prev = hook;
488 else
490 hook_list->hooks = hook;
491 hook->next = sibling;
492 sibling->prev = hook;
495 else
497 if (hook_list->hooks)
499 sibling = hook_list->hooks;
500 while (sibling->next)
501 sibling = sibling->next;
502 hook->prev = sibling;
503 sibling->next = hook;
505 else
506 hook_list->hooks = hook;
511 * g_hook_list_invoke:
512 * @hook_list: a #GHookList
513 * @may_recurse: %TRUE if functions which are already running
514 * (e.g. in another thread) can be called. If set to %FALSE,
515 * these are skipped
517 * Calls all of the #GHook functions in a #GHookList.
519 void
520 g_hook_list_invoke (GHookList *hook_list,
521 gboolean may_recurse)
523 GHook *hook;
525 g_return_if_fail (hook_list != NULL);
526 g_return_if_fail (hook_list->is_setup);
528 hook = g_hook_first_valid (hook_list, may_recurse);
529 while (hook)
531 GHookFunc func;
532 gboolean was_in_call;
534 func = (GHookFunc) hook->func;
536 was_in_call = G_HOOK_IN_CALL (hook);
537 hook->flags |= G_HOOK_FLAG_IN_CALL;
538 func (hook->data);
539 if (!was_in_call)
540 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
542 hook = g_hook_next_valid (hook_list, hook, may_recurse);
547 * g_hook_list_invoke_check:
548 * @hook_list: a #GHookList
549 * @may_recurse: %TRUE if functions which are already running
550 * (e.g. in another thread) can be called. If set to %FALSE,
551 * these are skipped
553 * Calls all of the #GHook functions in a #GHookList.
554 * Any function which returns %FALSE is removed from the #GHookList.
556 void
557 g_hook_list_invoke_check (GHookList *hook_list,
558 gboolean may_recurse)
560 GHook *hook;
562 g_return_if_fail (hook_list != NULL);
563 g_return_if_fail (hook_list->is_setup);
565 hook = g_hook_first_valid (hook_list, may_recurse);
566 while (hook)
568 GHookCheckFunc func;
569 gboolean was_in_call;
570 gboolean need_destroy;
572 func = (GHookCheckFunc) hook->func;
574 was_in_call = G_HOOK_IN_CALL (hook);
575 hook->flags |= G_HOOK_FLAG_IN_CALL;
576 need_destroy = !func (hook->data);
577 if (!was_in_call)
578 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
579 if (need_destroy)
580 g_hook_destroy_link (hook_list, hook);
582 hook = g_hook_next_valid (hook_list, hook, may_recurse);
587 * GHookCheckMarshaller:
588 * @hook: a #GHook
589 * @marshal_data: user data
591 * Defines the type of function used by g_hook_list_marshal_check().
593 * Returns: %FALSE if @hook should be destroyed
597 * g_hook_list_marshal_check:
598 * @hook_list: a #GHookList
599 * @may_recurse: %TRUE if hooks which are currently running
600 * (e.g. in another thread) are considered valid. If set to %FALSE,
601 * these are skipped
602 * @marshaller: the function to call for each #GHook
603 * @marshal_data: data to pass to @marshaller
605 * Calls a function on each valid #GHook and destroys it if the
606 * function returns %FALSE.
608 void
609 g_hook_list_marshal_check (GHookList *hook_list,
610 gboolean may_recurse,
611 GHookCheckMarshaller marshaller,
612 gpointer data)
614 GHook *hook;
616 g_return_if_fail (hook_list != NULL);
617 g_return_if_fail (hook_list->is_setup);
618 g_return_if_fail (marshaller != NULL);
620 hook = g_hook_first_valid (hook_list, may_recurse);
621 while (hook)
623 gboolean was_in_call;
624 gboolean need_destroy;
626 was_in_call = G_HOOK_IN_CALL (hook);
627 hook->flags |= G_HOOK_FLAG_IN_CALL;
628 need_destroy = !marshaller (hook, data);
629 if (!was_in_call)
630 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
631 if (need_destroy)
632 g_hook_destroy_link (hook_list, hook);
634 hook = g_hook_next_valid (hook_list, hook, may_recurse);
639 * GHookMarshaller:
640 * @hook: a #GHook
641 * @marshal_data: user data
643 * Defines the type of function used by g_hook_list_marshal().
647 * g_hook_list_marshal:
648 * @hook_list: a #GHookList
649 * @may_recurse: %TRUE if hooks which are currently running
650 * (e.g. in another thread) are considered valid. If set to %FALSE,
651 * these are skipped
652 * @marshaller: the function to call for each #GHook
653 * @marshal_data: data to pass to @marshaller
655 * Calls a function on each valid #GHook.
657 void
658 g_hook_list_marshal (GHookList *hook_list,
659 gboolean may_recurse,
660 GHookMarshaller marshaller,
661 gpointer data)
663 GHook *hook;
665 g_return_if_fail (hook_list != NULL);
666 g_return_if_fail (hook_list->is_setup);
667 g_return_if_fail (marshaller != NULL);
669 hook = g_hook_first_valid (hook_list, may_recurse);
670 while (hook)
672 gboolean was_in_call;
674 was_in_call = G_HOOK_IN_CALL (hook);
675 hook->flags |= G_HOOK_FLAG_IN_CALL;
676 marshaller (hook, data);
677 if (!was_in_call)
678 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
680 hook = g_hook_next_valid (hook_list, hook, may_recurse);
685 * g_hook_first_valid:
686 * @hook_list: a #GHookList
687 * @may_be_in_call: %TRUE if hooks which are currently running
688 * (e.g. in another thread) are considered valid. If set to %FALSE,
689 * these are skipped
691 * Returns the first #GHook in a #GHookList which has not been destroyed.
692 * The reference count for the #GHook is incremented, so you must call
693 * g_hook_unref() to restore it when no longer needed. (Or call
694 * g_hook_next_valid() if you are stepping through the #GHookList.)
696 * Returns: the first valid #GHook, or %NULL if none are valid
698 GHook*
699 g_hook_first_valid (GHookList *hook_list,
700 gboolean may_be_in_call)
702 g_return_val_if_fail (hook_list != NULL, NULL);
704 if (hook_list->is_setup)
706 GHook *hook;
708 hook = hook_list->hooks;
709 if (hook)
711 g_hook_ref (hook_list, hook);
712 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
713 return hook;
714 else
715 return g_hook_next_valid (hook_list, hook, may_be_in_call);
719 return NULL;
723 * g_hook_next_valid:
724 * @hook_list: a #GHookList
725 * @hook: the current #GHook
726 * @may_be_in_call: %TRUE if hooks which are currently running
727 * (e.g. in another thread) are considered valid. If set to %FALSE,
728 * these are skipped
730 * Returns the next #GHook in a #GHookList which has not been destroyed.
731 * The reference count for the #GHook is incremented, so you must call
732 * g_hook_unref() to restore it when no longer needed. (Or continue to call
733 * g_hook_next_valid() until %NULL is returned.)
735 * Returns: the next valid #GHook, or %NULL if none are valid
737 GHook*
738 g_hook_next_valid (GHookList *hook_list,
739 GHook *hook,
740 gboolean may_be_in_call)
742 GHook *ohook = hook;
744 g_return_val_if_fail (hook_list != NULL, NULL);
746 if (!hook)
747 return NULL;
749 hook = hook->next;
750 while (hook)
752 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
754 g_hook_ref (hook_list, hook);
755 g_hook_unref (hook_list, ohook);
757 return hook;
759 hook = hook->next;
761 g_hook_unref (hook_list, ohook);
763 return NULL;
767 * g_hook_get:
768 * @hook_list: a #GHookList
769 * @hook_id: a hook id
771 * Returns the #GHook with the given id, or %NULL if it is not found.
773 * Returns: the #GHook with the given id, or %NULL if it is not found
775 GHook*
776 g_hook_get (GHookList *hook_list,
777 gulong hook_id)
779 GHook *hook;
781 g_return_val_if_fail (hook_list != NULL, NULL);
782 g_return_val_if_fail (hook_id > 0, NULL);
784 hook = hook_list->hooks;
785 while (hook)
787 if (hook->hook_id == hook_id)
788 return hook;
789 hook = hook->next;
792 return NULL;
796 * GHookFindFunc:
797 * @hook: a #GHook
798 * @data: user data passed to g_hook_find_func()
800 * Defines the type of the function passed to g_hook_find().
802 * Returns: %TRUE if the required #GHook has been found
806 * g_hook_find:
807 * @hook_list: a #GHookList
808 * @need_valids: %TRUE if #GHook elements which have been destroyed
809 * should be skipped
810 * @func: the function to call for each #GHook, which should return
811 * %TRUE when the #GHook has been found
812 * @data: the data to pass to @func
814 * Finds a #GHook in a #GHookList using the given function to
815 * test for a match.
817 * Returns: the found #GHook or %NULL if no matching #GHook is found
819 GHook*
820 g_hook_find (GHookList *hook_list,
821 gboolean need_valids,
822 GHookFindFunc func,
823 gpointer data)
825 GHook *hook;
827 g_return_val_if_fail (hook_list != NULL, NULL);
828 g_return_val_if_fail (func != NULL, NULL);
830 hook = hook_list->hooks;
831 while (hook)
833 GHook *tmp;
835 /* test only non-destroyed hooks */
836 if (!hook->hook_id)
838 hook = hook->next;
839 continue;
842 g_hook_ref (hook_list, hook);
844 if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
846 g_hook_unref (hook_list, hook);
848 return hook;
851 tmp = hook->next;
852 g_hook_unref (hook_list, hook);
853 hook = tmp;
856 return NULL;
860 * g_hook_find_data:
861 * @hook_list: a #GHookList
862 * @need_valids: %TRUE if #GHook elements which have been destroyed
863 * should be skipped
864 * @data: the data to find
866 * Finds a #GHook in a #GHookList with the given data.
868 * Returns: the #GHook with the given @data or %NULL if no matching
869 * #GHook is found
871 GHook*
872 g_hook_find_data (GHookList *hook_list,
873 gboolean need_valids,
874 gpointer data)
876 GHook *hook;
878 g_return_val_if_fail (hook_list != NULL, NULL);
880 hook = hook_list->hooks;
881 while (hook)
883 /* test only non-destroyed hooks */
884 if (hook->data == data &&
885 hook->hook_id &&
886 (!need_valids || G_HOOK_ACTIVE (hook)))
887 return hook;
889 hook = hook->next;
892 return NULL;
896 * g_hook_find_func:
897 * @hook_list: a #GHookList
898 * @need_valids: %TRUE if #GHook elements which have been destroyed
899 * should be skipped
900 * @func: the function to find
902 * Finds a #GHook in a #GHookList with the given function.
904 * Returns: the #GHook with the given @func or %NULL if no matching
905 * #GHook is found
907 GHook*
908 g_hook_find_func (GHookList *hook_list,
909 gboolean need_valids,
910 gpointer func)
912 GHook *hook;
914 g_return_val_if_fail (hook_list != NULL, NULL);
915 g_return_val_if_fail (func != NULL, NULL);
917 hook = hook_list->hooks;
918 while (hook)
920 /* test only non-destroyed hooks */
921 if (hook->func == func &&
922 hook->hook_id &&
923 (!need_valids || G_HOOK_ACTIVE (hook)))
924 return hook;
926 hook = hook->next;
929 return NULL;
933 * g_hook_find_func_data:
934 * @hook_list: a #GHookList
935 * @need_valids: %TRUE if #GHook elements which have been destroyed
936 * should be skipped
937 * @func: the function to find
938 * @data: the data to find
940 * Finds a #GHook in a #GHookList with the given function and data.
942 * Returns: the #GHook with the given @func and @data or %NULL if
943 * no matching #GHook is found
945 GHook*
946 g_hook_find_func_data (GHookList *hook_list,
947 gboolean need_valids,
948 gpointer func,
949 gpointer data)
951 GHook *hook;
953 g_return_val_if_fail (hook_list != NULL, NULL);
954 g_return_val_if_fail (func != NULL, NULL);
956 hook = hook_list->hooks;
957 while (hook)
959 /* test only non-destroyed hooks */
960 if (hook->data == data &&
961 hook->func == func &&
962 hook->hook_id &&
963 (!need_valids || G_HOOK_ACTIVE (hook)))
964 return hook;
966 hook = hook->next;
969 return NULL;
973 * GHookCompareFunc:
974 * @new_hook: the #GHook being inserted
975 * @sibling: the #GHook to compare with @new_hook
977 * Defines the type of function used to compare #GHook elements in
978 * g_hook_insert_sorted().
980 * Returns: a value &lt;= 0 if @new_hook should be before @sibling
984 * g_hook_insert_sorted:
985 * @hook_list: a #GHookList
986 * @hook: the #GHook to insert
987 * @func: the comparison function used to sort the #GHook elements
989 * Inserts a #GHook into a #GHookList, sorted by the given function.
991 void
992 g_hook_insert_sorted (GHookList *hook_list,
993 GHook *hook,
994 GHookCompareFunc func)
996 GHook *sibling;
998 g_return_if_fail (hook_list != NULL);
999 g_return_if_fail (hook_list->is_setup);
1000 g_return_if_fail (hook != NULL);
1001 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
1002 g_return_if_fail (hook->func != NULL);
1003 g_return_if_fail (func != NULL);
1005 /* first non-destroyed hook */
1006 sibling = hook_list->hooks;
1007 while (sibling && !sibling->hook_id)
1008 sibling = sibling->next;
1010 while (sibling)
1012 GHook *tmp;
1014 g_hook_ref (hook_list, sibling);
1015 if (func (hook, sibling) <= 0 && sibling->hook_id)
1017 g_hook_unref (hook_list, sibling);
1018 break;
1021 /* next non-destroyed hook */
1022 tmp = sibling->next;
1023 while (tmp && !tmp->hook_id)
1024 tmp = tmp->next;
1026 g_hook_unref (hook_list, sibling);
1027 sibling = tmp;
1031 g_hook_insert_before (hook_list, sibling, hook);
1035 * g_hook_compare_ids:
1036 * @new_hook: a #GHook
1037 * @sibling: a #GHook to compare with @new_hook
1039 * Compares the ids of two #GHook elements, returning a negative value
1040 * if the second id is greater than the first.
1042 * Returns: a value &lt;= 0 if the id of @sibling is >= the id of @new_hook
1044 gint
1045 g_hook_compare_ids (GHook *new_hook,
1046 GHook *sibling)
1048 if (new_hook->hook_id < sibling->hook_id)
1049 return -1;
1050 else if (new_hook->hook_id > sibling->hook_id)
1051 return 1;
1053 return 0;