Remove redundant header inclusions
[glib.git] / glib / ghook.c
blob39f36bb72532d5c2e5529370c229277e3271d431
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/.
30 /*
31 * MT safe
34 #include "config.h"
36 #include "glib.h"
39 /* --- functions --- */
40 static void
41 default_finalize_hook (GHookList *hook_list,
42 GHook *hook)
44 GDestroyNotify destroy = hook->destroy;
46 if (destroy)
48 hook->destroy = NULL;
49 destroy (hook->data);
53 void
54 g_hook_list_init (GHookList *hook_list,
55 guint hook_size)
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;
70 void
71 g_hook_list_clear (GHookList *hook_list)
73 g_return_if_fail (hook_list != NULL);
75 if (hook_list->is_setup)
77 GHook *hook;
79 hook_list->is_setup = FALSE;
81 hook = hook_list->hooks;
82 if (!hook)
84 /* destroy hook_list->hook_memchunk */
86 else
89 GHook *tmp;
91 g_hook_ref (hook_list, hook);
92 g_hook_destroy_link (hook_list, hook);
93 tmp = hook->next;
94 g_hook_unref (hook_list, hook);
95 hook = tmp;
97 while (hook);
101 GHook*
102 g_hook_alloc (GHookList *hook_list)
104 GHook *hook;
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);
110 hook->data = NULL;
111 hook->next = NULL;
112 hook->prev = NULL;
113 hook->flags = G_HOOK_FLAG_ACTIVE;
114 hook->ref_count = 0;
115 hook->hook_id = 0;
116 hook->func = NULL;
117 hook->destroy = NULL;
119 return hook;
122 void
123 g_hook_free (GHookList *hook_list,
124 GHook *hook)
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);
137 void
138 g_hook_destroy_link (GHookList *hook_list,
139 GHook *hook)
141 g_return_if_fail (hook_list != NULL);
142 g_return_if_fail (hook != NULL);
144 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
145 if (hook->hook_id)
147 hook->hook_id = 0;
148 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
152 gboolean
153 g_hook_destroy (GHookList *hook_list,
154 gulong hook_id)
156 GHook *hook;
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);
162 if (hook)
164 g_hook_destroy_link (hook_list, hook);
165 return TRUE;
168 return FALSE;
171 void
172 g_hook_unref (GHookList *hook_list,
173 GHook *hook)
175 g_return_if_fail (hook_list != NULL);
176 g_return_if_fail (hook != NULL);
177 g_return_if_fail (hook->ref_count > 0);
179 hook->ref_count--;
180 if (!hook->ref_count)
182 g_return_if_fail (hook->hook_id == 0);
183 g_return_if_fail (!G_HOOK_IN_CALL (hook));
185 if (hook->prev)
186 hook->prev->next = hook->next;
187 else
188 hook_list->hooks = hook->next;
189 if (hook->next)
191 hook->next->prev = hook->prev;
192 hook->next = NULL;
194 hook->prev = NULL;
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 */
207 else
208 g_hook_free (hook_list, hook);
212 GHook *
213 g_hook_ref (GHookList *hook_list,
214 GHook *hook)
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);
220 hook->ref_count++;
222 return hook;
225 void
226 g_hook_prepend (GHookList *hook_list,
227 GHook *hook)
229 g_return_if_fail (hook_list != NULL);
231 g_hook_insert_before (hook_list, hook_list->hooks, hook);
234 void
235 g_hook_insert_before (GHookList *hook_list,
236 GHook *sibling,
237 GHook *hook)
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 */
248 if (sibling)
250 if (sibling->prev)
252 hook->prev = sibling->prev;
253 hook->prev->next = hook;
254 hook->next = sibling;
255 sibling->prev = hook;
257 else
259 hook_list->hooks = hook;
260 hook->next = sibling;
261 sibling->prev = hook;
264 else
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;
274 else
275 hook_list->hooks = hook;
279 void
280 g_hook_list_invoke (GHookList *hook_list,
281 gboolean may_recurse)
283 GHook *hook;
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);
289 while (hook)
291 GHookFunc func;
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;
298 func (hook->data);
299 if (!was_in_call)
300 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
302 hook = g_hook_next_valid (hook_list, hook, may_recurse);
306 void
307 g_hook_list_invoke_check (GHookList *hook_list,
308 gboolean may_recurse)
310 GHook *hook;
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);
316 while (hook)
318 GHookCheckFunc func;
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);
327 if (!was_in_call)
328 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
329 if (need_destroy)
330 g_hook_destroy_link (hook_list, hook);
332 hook = g_hook_next_valid (hook_list, hook, may_recurse);
336 void
337 g_hook_list_marshal_check (GHookList *hook_list,
338 gboolean may_recurse,
339 GHookCheckMarshaller marshaller,
340 gpointer data)
342 GHook *hook;
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);
349 while (hook)
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);
357 if (!was_in_call)
358 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
359 if (need_destroy)
360 g_hook_destroy_link (hook_list, hook);
362 hook = g_hook_next_valid (hook_list, hook, may_recurse);
366 void
367 g_hook_list_marshal (GHookList *hook_list,
368 gboolean may_recurse,
369 GHookMarshaller marshaller,
370 gpointer data)
372 GHook *hook;
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);
379 while (hook)
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);
386 if (!was_in_call)
387 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
389 hook = g_hook_next_valid (hook_list, hook, may_recurse);
393 GHook*
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)
401 GHook *hook;
403 hook = hook_list->hooks;
404 if (hook)
406 g_hook_ref (hook_list, hook);
407 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
408 return hook;
409 else
410 return g_hook_next_valid (hook_list, hook, may_be_in_call);
414 return NULL;
417 GHook*
418 g_hook_next_valid (GHookList *hook_list,
419 GHook *hook,
420 gboolean may_be_in_call)
422 GHook *ohook = hook;
424 g_return_val_if_fail (hook_list != NULL, NULL);
426 if (!hook)
427 return NULL;
429 hook = hook->next;
430 while (hook)
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);
437 return hook;
439 hook = hook->next;
441 g_hook_unref (hook_list, ohook);
443 return NULL;
446 GHook*
447 g_hook_get (GHookList *hook_list,
448 gulong hook_id)
450 GHook *hook;
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;
456 while (hook)
458 if (hook->hook_id == hook_id)
459 return hook;
460 hook = hook->next;
463 return NULL;
466 GHook*
467 g_hook_find (GHookList *hook_list,
468 gboolean need_valids,
469 GHookFindFunc func,
470 gpointer data)
472 GHook *hook;
474 g_return_val_if_fail (hook_list != NULL, NULL);
475 g_return_val_if_fail (func != NULL, NULL);
477 hook = hook_list->hooks;
478 while (hook)
480 GHook *tmp;
482 /* test only non-destroyed hooks */
483 if (!hook->hook_id)
485 hook = hook->next;
486 continue;
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);
495 return hook;
498 tmp = hook->next;
499 g_hook_unref (hook_list, hook);
500 hook = tmp;
503 return NULL;
506 GHook*
507 g_hook_find_data (GHookList *hook_list,
508 gboolean need_valids,
509 gpointer data)
511 GHook *hook;
513 g_return_val_if_fail (hook_list != NULL, NULL);
515 hook = hook_list->hooks;
516 while (hook)
518 /* test only non-destroyed hooks */
519 if (hook->data == data &&
520 hook->hook_id &&
521 (!need_valids || G_HOOK_ACTIVE (hook)))
522 return hook;
524 hook = hook->next;
527 return NULL;
530 GHook*
531 g_hook_find_func (GHookList *hook_list,
532 gboolean need_valids,
533 gpointer func)
535 GHook *hook;
537 g_return_val_if_fail (hook_list != NULL, NULL);
538 g_return_val_if_fail (func != NULL, NULL);
540 hook = hook_list->hooks;
541 while (hook)
543 /* test only non-destroyed hooks */
544 if (hook->func == func &&
545 hook->hook_id &&
546 (!need_valids || G_HOOK_ACTIVE (hook)))
547 return hook;
549 hook = hook->next;
552 return NULL;
555 GHook*
556 g_hook_find_func_data (GHookList *hook_list,
557 gboolean need_valids,
558 gpointer func,
559 gpointer data)
561 GHook *hook;
563 g_return_val_if_fail (hook_list != NULL, NULL);
564 g_return_val_if_fail (func != NULL, NULL);
566 hook = hook_list->hooks;
567 while (hook)
569 /* test only non-destroyed hooks */
570 if (hook->data == data &&
571 hook->func == func &&
572 hook->hook_id &&
573 (!need_valids || G_HOOK_ACTIVE (hook)))
574 return hook;
576 hook = hook->next;
579 return NULL;
582 void
583 g_hook_insert_sorted (GHookList *hook_list,
584 GHook *hook,
585 GHookCompareFunc func)
587 GHook *sibling;
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;
601 while (sibling)
603 GHook *tmp;
605 g_hook_ref (hook_list, sibling);
606 if (func (hook, sibling) <= 0 && sibling->hook_id)
608 g_hook_unref (hook_list, sibling);
609 break;
612 /* next non-destroyed hook */
613 tmp = sibling->next;
614 while (tmp && !tmp->hook_id)
615 tmp = tmp->next;
617 g_hook_unref (hook_list, sibling);
618 sibling = tmp;
621 g_hook_insert_before (hook_list, sibling, hook);
624 gint
625 g_hook_compare_ids (GHook *new_hook,
626 GHook *sibling)
628 if (new_hook->hook_id < sibling->hook_id)
629 return -1;
630 else if (new_hook->hook_id > sibling->hook_id)
631 return 1;
633 return 0;