Avoid forcing extra newlines when using template files. (#171005)
[glib.git] / glib / ghook.c
blob88ff448a5bbc011d72ebb350da5499144027e305
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"
37 #include "galias.h"
40 /* --- defines --- */
41 #define G_HOOKS_PREALLOC (16)
44 /* --- functions --- */
45 static void
46 default_finalize_hook (GHookList *hook_list,
47 GHook *hook)
49 GDestroyNotify destroy = hook->destroy;
51 if (destroy)
53 hook->destroy = NULL;
54 destroy (hook->data);
58 void
59 g_hook_list_init (GHookList *hook_list,
60 guint hook_size)
62 g_return_if_fail (hook_list != NULL);
63 g_return_if_fail (hook_size >= sizeof (GHook));
64 g_return_if_fail (hook_size < 65536);
66 hook_list->seq_id = 1;
67 hook_list->hook_size = hook_size;
68 hook_list->is_setup = TRUE;
69 hook_list->hooks = NULL;
70 hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk",
71 hook_size,
72 hook_size * G_HOOKS_PREALLOC,
73 G_ALLOC_AND_FREE);
74 hook_list->finalize_hook = default_finalize_hook;
75 hook_list->dummy[0] = NULL;
76 hook_list->dummy[1] = NULL;
79 void
80 g_hook_list_clear (GHookList *hook_list)
82 g_return_if_fail (hook_list != NULL);
84 if (hook_list->is_setup)
86 GHook *hook;
88 hook_list->is_setup = FALSE;
90 hook = hook_list->hooks;
91 if (!hook)
93 g_mem_chunk_destroy (hook_list->hook_memchunk);
94 hook_list->hook_memchunk = NULL;
96 else
99 GHook *tmp;
101 g_hook_ref (hook_list, hook);
102 g_hook_destroy_link (hook_list, hook);
103 tmp = hook->next;
104 g_hook_unref (hook_list, hook);
105 hook = tmp;
107 while (hook);
108 if (hook_list->hook_memchunk)
109 g_warning (G_STRLOC ": failed to clear hooklist, unconsolidated references on hooks left");
113 GHook*
114 g_hook_alloc (GHookList *hook_list)
116 GHook *hook;
118 g_return_val_if_fail (hook_list != NULL, NULL);
119 g_return_val_if_fail (hook_list->is_setup, NULL);
121 hook = g_chunk_new0 (GHook, hook_list->hook_memchunk);
122 hook->data = NULL;
123 hook->next = NULL;
124 hook->prev = NULL;
125 hook->flags = G_HOOK_FLAG_ACTIVE;
126 hook->ref_count = 0;
127 hook->hook_id = 0;
128 hook->func = NULL;
129 hook->destroy = NULL;
131 return hook;
134 void
135 g_hook_free (GHookList *hook_list,
136 GHook *hook)
138 g_return_if_fail (hook_list != NULL);
139 g_return_if_fail (hook_list->is_setup);
140 g_return_if_fail (hook != NULL);
141 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
142 g_return_if_fail (!G_HOOK_IN_CALL (hook));
144 hook_list->finalize_hook (hook_list, hook);
145 g_chunk_free (hook, hook_list->hook_memchunk);
148 void
149 g_hook_destroy_link (GHookList *hook_list,
150 GHook *hook)
152 g_return_if_fail (hook_list != NULL);
153 g_return_if_fail (hook != NULL);
155 hook->flags &= ~G_HOOK_FLAG_ACTIVE;
156 if (hook->hook_id)
158 hook->hook_id = 0;
159 g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
163 gboolean
164 g_hook_destroy (GHookList *hook_list,
165 gulong hook_id)
167 GHook *hook;
169 g_return_val_if_fail (hook_list != NULL, FALSE);
170 g_return_val_if_fail (hook_id > 0, FALSE);
172 hook = g_hook_get (hook_list, hook_id);
173 if (hook)
175 g_hook_destroy_link (hook_list, hook);
176 return TRUE;
179 return FALSE;
182 void
183 g_hook_unref (GHookList *hook_list,
184 GHook *hook)
186 g_return_if_fail (hook_list != NULL);
187 g_return_if_fail (hook_list->hook_memchunk != NULL);
188 g_return_if_fail (hook != NULL);
189 g_return_if_fail (hook->ref_count > 0);
191 hook->ref_count--;
192 if (!hook->ref_count)
194 g_return_if_fail (hook->hook_id == 0);
195 g_return_if_fail (!G_HOOK_IN_CALL (hook));
197 if (hook->prev)
198 hook->prev->next = hook->next;
199 else
200 hook_list->hooks = hook->next;
201 if (hook->next)
203 hook->next->prev = hook->prev;
204 hook->next = NULL;
206 hook->prev = NULL;
208 if (!hook_list->is_setup)
210 hook_list->is_setup = TRUE;
211 g_hook_free (hook_list, hook);
212 hook_list->is_setup = FALSE;
214 if (!hook_list->hooks)
216 g_mem_chunk_destroy (hook_list->hook_memchunk);
217 hook_list->hook_memchunk = NULL;
220 else
221 g_hook_free (hook_list, hook);
225 GHook *
226 g_hook_ref (GHookList *hook_list,
227 GHook *hook)
229 g_return_val_if_fail (hook_list != NULL, NULL);
230 g_return_val_if_fail (hook != NULL, NULL);
231 g_return_val_if_fail (hook->ref_count > 0, NULL);
233 hook->ref_count++;
235 return hook;
238 void
239 g_hook_prepend (GHookList *hook_list,
240 GHook *hook)
242 g_return_if_fail (hook_list != NULL);
244 g_hook_insert_before (hook_list, hook_list->hooks, hook);
247 void
248 g_hook_insert_before (GHookList *hook_list,
249 GHook *sibling,
250 GHook *hook)
252 g_return_if_fail (hook_list != NULL);
253 g_return_if_fail (hook_list->is_setup);
254 g_return_if_fail (hook != NULL);
255 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
256 g_return_if_fail (hook->ref_count == 0);
258 hook->hook_id = hook_list->seq_id++;
259 hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
261 if (sibling)
263 if (sibling->prev)
265 hook->prev = sibling->prev;
266 hook->prev->next = hook;
267 hook->next = sibling;
268 sibling->prev = hook;
270 else
272 hook_list->hooks = hook;
273 hook->next = sibling;
274 sibling->prev = hook;
277 else
279 if (hook_list->hooks)
281 sibling = hook_list->hooks;
282 while (sibling->next)
283 sibling = sibling->next;
284 hook->prev = sibling;
285 sibling->next = hook;
287 else
288 hook_list->hooks = hook;
292 void
293 g_hook_list_invoke (GHookList *hook_list,
294 gboolean may_recurse)
296 GHook *hook;
298 g_return_if_fail (hook_list != NULL);
299 g_return_if_fail (hook_list->is_setup);
301 hook = g_hook_first_valid (hook_list, may_recurse);
302 while (hook)
304 GHookFunc func;
305 gboolean was_in_call;
307 func = (GHookFunc) hook->func;
309 was_in_call = G_HOOK_IN_CALL (hook);
310 hook->flags |= G_HOOK_FLAG_IN_CALL;
311 func (hook->data);
312 if (!was_in_call)
313 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
315 hook = g_hook_next_valid (hook_list, hook, may_recurse);
319 void
320 g_hook_list_invoke_check (GHookList *hook_list,
321 gboolean may_recurse)
323 GHook *hook;
325 g_return_if_fail (hook_list != NULL);
326 g_return_if_fail (hook_list->is_setup);
328 hook = g_hook_first_valid (hook_list, may_recurse);
329 while (hook)
331 GHookCheckFunc func;
332 gboolean was_in_call;
333 gboolean need_destroy;
335 func = (GHookCheckFunc) hook->func;
337 was_in_call = G_HOOK_IN_CALL (hook);
338 hook->flags |= G_HOOK_FLAG_IN_CALL;
339 need_destroy = !func (hook->data);
340 if (!was_in_call)
341 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
342 if (need_destroy)
343 g_hook_destroy_link (hook_list, hook);
345 hook = g_hook_next_valid (hook_list, hook, may_recurse);
349 void
350 g_hook_list_marshal_check (GHookList *hook_list,
351 gboolean may_recurse,
352 GHookCheckMarshaller marshaller,
353 gpointer data)
355 GHook *hook;
357 g_return_if_fail (hook_list != NULL);
358 g_return_if_fail (hook_list->is_setup);
359 g_return_if_fail (marshaller != NULL);
361 hook = g_hook_first_valid (hook_list, may_recurse);
362 while (hook)
364 gboolean was_in_call;
365 gboolean need_destroy;
367 was_in_call = G_HOOK_IN_CALL (hook);
368 hook->flags |= G_HOOK_FLAG_IN_CALL;
369 need_destroy = !marshaller (hook, data);
370 if (!was_in_call)
371 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
372 if (need_destroy)
373 g_hook_destroy_link (hook_list, hook);
375 hook = g_hook_next_valid (hook_list, hook, may_recurse);
379 void
380 g_hook_list_marshal (GHookList *hook_list,
381 gboolean may_recurse,
382 GHookMarshaller marshaller,
383 gpointer data)
385 GHook *hook;
387 g_return_if_fail (hook_list != NULL);
388 g_return_if_fail (hook_list->is_setup);
389 g_return_if_fail (marshaller != NULL);
391 hook = g_hook_first_valid (hook_list, may_recurse);
392 while (hook)
394 gboolean was_in_call;
396 was_in_call = G_HOOK_IN_CALL (hook);
397 hook->flags |= G_HOOK_FLAG_IN_CALL;
398 marshaller (hook, data);
399 if (!was_in_call)
400 hook->flags &= ~G_HOOK_FLAG_IN_CALL;
402 hook = g_hook_next_valid (hook_list, hook, may_recurse);
406 GHook*
407 g_hook_first_valid (GHookList *hook_list,
408 gboolean may_be_in_call)
410 g_return_val_if_fail (hook_list != NULL, NULL);
412 if (hook_list->is_setup)
414 GHook *hook;
416 hook = hook_list->hooks;
417 if (hook)
419 g_hook_ref (hook_list, hook);
420 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
421 return hook;
422 else
423 return g_hook_next_valid (hook_list, hook, may_be_in_call);
427 return NULL;
430 GHook*
431 g_hook_next_valid (GHookList *hook_list,
432 GHook *hook,
433 gboolean may_be_in_call)
435 GHook *ohook = hook;
437 g_return_val_if_fail (hook_list != NULL, NULL);
439 if (!hook)
440 return NULL;
442 hook = hook->next;
443 while (hook)
445 if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
447 g_hook_ref (hook_list, hook);
448 g_hook_unref (hook_list, ohook);
450 return hook;
452 hook = hook->next;
454 g_hook_unref (hook_list, ohook);
456 return NULL;
459 GHook*
460 g_hook_get (GHookList *hook_list,
461 gulong hook_id)
463 GHook *hook;
465 g_return_val_if_fail (hook_list != NULL, NULL);
466 g_return_val_if_fail (hook_id > 0, NULL);
468 hook = hook_list->hooks;
469 while (hook)
471 if (hook->hook_id == hook_id)
472 return hook;
473 hook = hook->next;
476 return NULL;
479 GHook*
480 g_hook_find (GHookList *hook_list,
481 gboolean need_valids,
482 GHookFindFunc func,
483 gpointer data)
485 GHook *hook;
487 g_return_val_if_fail (hook_list != NULL, NULL);
488 g_return_val_if_fail (func != NULL, NULL);
490 hook = hook_list->hooks;
491 while (hook)
493 GHook *tmp;
495 /* test only non-destroyed hooks */
496 if (!hook->hook_id)
498 hook = hook->next;
499 continue;
502 g_hook_ref (hook_list, hook);
504 if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
506 g_hook_unref (hook_list, hook);
508 return hook;
511 tmp = hook->next;
512 g_hook_unref (hook_list, hook);
513 hook = tmp;
516 return NULL;
519 GHook*
520 g_hook_find_data (GHookList *hook_list,
521 gboolean need_valids,
522 gpointer data)
524 GHook *hook;
526 g_return_val_if_fail (hook_list != NULL, NULL);
528 hook = hook_list->hooks;
529 while (hook)
531 /* test only non-destroyed hooks */
532 if (hook->data == data &&
533 hook->hook_id &&
534 (!need_valids || G_HOOK_ACTIVE (hook)))
535 return hook;
537 hook = hook->next;
540 return NULL;
543 GHook*
544 g_hook_find_func (GHookList *hook_list,
545 gboolean need_valids,
546 gpointer func)
548 GHook *hook;
550 g_return_val_if_fail (hook_list != NULL, NULL);
551 g_return_val_if_fail (func != NULL, NULL);
553 hook = hook_list->hooks;
554 while (hook)
556 /* test only non-destroyed hooks */
557 if (hook->func == func &&
558 hook->hook_id &&
559 (!need_valids || G_HOOK_ACTIVE (hook)))
560 return hook;
562 hook = hook->next;
565 return NULL;
568 GHook*
569 g_hook_find_func_data (GHookList *hook_list,
570 gboolean need_valids,
571 gpointer func,
572 gpointer data)
574 GHook *hook;
576 g_return_val_if_fail (hook_list != NULL, NULL);
577 g_return_val_if_fail (func != NULL, NULL);
579 hook = hook_list->hooks;
580 while (hook)
582 /* test only non-destroyed hooks */
583 if (hook->data == data &&
584 hook->func == func &&
585 hook->hook_id &&
586 (!need_valids || G_HOOK_ACTIVE (hook)))
587 return hook;
589 hook = hook->next;
592 return NULL;
595 void
596 g_hook_insert_sorted (GHookList *hook_list,
597 GHook *hook,
598 GHookCompareFunc func)
600 GHook *sibling;
602 g_return_if_fail (hook_list != NULL);
603 g_return_if_fail (hook_list->is_setup);
604 g_return_if_fail (hook != NULL);
605 g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
606 g_return_if_fail (hook->func != NULL);
607 g_return_if_fail (func != NULL);
609 /* first non-destroyed hook */
610 sibling = hook_list->hooks;
611 while (sibling && !sibling->hook_id)
612 sibling = sibling->next;
614 while (sibling)
616 GHook *tmp;
618 g_hook_ref (hook_list, sibling);
619 if (func (hook, sibling) <= 0 && sibling->hook_id)
621 g_hook_unref (hook_list, sibling);
622 break;
625 /* next non-destroyed hook */
626 tmp = sibling->next;
627 while (tmp && !tmp->hook_id)
628 tmp = tmp->next;
630 g_hook_unref (hook_list, sibling);
631 sibling = tmp;
634 g_hook_insert_before (hook_list, sibling, hook);
637 gint
638 g_hook_compare_ids (GHook *new_hook,
639 GHook *sibling)
641 if (new_hook->hook_id < sibling->hook_id)
642 return -1;
643 else if (new_hook->hook_id > sibling->hook_id)
644 return 1;
646 return 0;
649 #define __G_HOOK_C__
650 #include "galiasdef.c"