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/.
39 /* --- functions --- */
41 default_finalize_hook (GHookList
*hook_list
,
44 GDestroyNotify destroy
= hook
->destroy
;
54 g_hook_list_init (GHookList
*hook_list
,
57 g_return_if_fail (hook_list
!= NULL
);
58 g_return_if_fail (hook_size
>= sizeof (GHook
));
60 hook_list
->seq_id
= 1;
61 hook_list
->hook_size
= hook_size
;
62 hook_list
->is_setup
= TRUE
;
63 hook_list
->hooks
= NULL
;
64 hook_list
->dummy3
= NULL
;
65 hook_list
->finalize_hook
= default_finalize_hook
;
66 hook_list
->dummy
[0] = NULL
;
67 hook_list
->dummy
[1] = NULL
;
71 g_hook_list_clear (GHookList
*hook_list
)
73 g_return_if_fail (hook_list
!= NULL
);
75 if (hook_list
->is_setup
)
79 hook_list
->is_setup
= FALSE
;
81 hook
= hook_list
->hooks
;
84 /* destroy hook_list->hook_memchunk */
91 g_hook_ref (hook_list
, hook
);
92 g_hook_destroy_link (hook_list
, hook
);
94 g_hook_unref (hook_list
, hook
);
102 g_hook_alloc (GHookList
*hook_list
)
106 g_return_val_if_fail (hook_list
!= NULL
, NULL
);
107 g_return_val_if_fail (hook_list
->is_setup
, NULL
);
109 hook
= g_slice_alloc0 (hook_list
->hook_size
);
113 hook
->flags
= G_HOOK_FLAG_ACTIVE
;
117 hook
->destroy
= NULL
;
123 g_hook_free (GHookList
*hook_list
,
126 g_return_if_fail (hook_list
!= NULL
);
127 g_return_if_fail (hook_list
->is_setup
);
128 g_return_if_fail (hook
!= NULL
);
129 g_return_if_fail (G_HOOK_IS_UNLINKED (hook
));
130 g_return_if_fail (!G_HOOK_IN_CALL (hook
));
132 if(hook_list
->finalize_hook
!= NULL
)
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
)