Coverage Report

Created: 2025-07-12 06:30

/src/tinysparql/subprojects/glib-2.80.3/glib/ghook.c
Line
Count
Source (jump to first uncovered line)
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3
 *
4
 * GHook: Callback maintenance functions
5
 * Copyright (C) 1998 Tim Janik
6
 *
7
 * SPDX-License-Identifier: LGPL-2.1-or-later
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/*
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/.
28
 */
29
30
/*
31
 * MT safe
32
 */
33
34
#include "config.h"
35
36
#include "ghook.h"
37
38
#include "gtestutils.h"
39
#include "gslice.h"
40
41
/**
42
 * GHookList:
43
 * @seq_id: the next free #GHook id
44
 * @hook_size: the size of the #GHookList elements, in bytes
45
 * @is_setup: 1 if the #GHookList has been initialized
46
 * @hooks: the first #GHook element in the list
47
 * @dummy3: unused
48
 * @finalize_hook: the function to call to finalize a #GHook element.
49
 *     The default behaviour is to call the hooks @destroy function
50
 * @dummy: unused
51
 *
52
 * The #GHookList struct represents a list of hook functions.
53
 */
54
55
/**
56
 * GHookFinalizeFunc:
57
 * @hook_list: a #GHookList
58
 * @hook: the hook in @hook_list that gets finalized
59
 *
60
 * Defines the type of function to be called when a hook in a
61
 * list of hooks gets finalized.
62
 */
63
64
/**
65
 * GHookFlagMask:
66
 * @G_HOOK_FLAG_ACTIVE: set if the hook has not been destroyed
67
 * @G_HOOK_FLAG_IN_CALL: set if the hook is currently being run
68
 * @G_HOOK_FLAG_MASK: A mask covering all bits reserved for
69
 *   hook flags; see %G_HOOK_FLAG_USER_SHIFT
70
 *
71
 * Flags used internally in the #GHook implementation.
72
 */
73
74
/**
75
 * G_HOOK_FLAGS:
76
 * @hook: a #GHook
77
 *
78
 * Gets the flags of a hook.
79
 */
80
81
/**
82
 * G_HOOK_FLAG_USER_SHIFT:
83
 *
84
 * The position of the first bit which is not reserved for internal
85
 * use be the #GHook implementation, i.e.
86
 * `1 << G_HOOK_FLAG_USER_SHIFT` is the first
87
 * bit which can be used for application-defined flags.
88
 */
89
90
/**
91
 * G_HOOK:
92
 * @hook: a pointer
93
 *
94
 * Casts a pointer to a `GHook*`.
95
 */
96
97
/**
98
 * G_HOOK_IS_VALID:
99
 * @hook: a #GHook
100
 *
101
 * Returns %TRUE if the #GHook is valid, i.e. it is in a #GHookList,
102
 * it is active and it has not been destroyed.
103
 *
104
 * Returns: %TRUE if the #GHook is valid
105
 */
106
107
/**
108
 * G_HOOK_ACTIVE:
109
 * @hook: a #GHook
110
 *
111
 * Returns %TRUE if the #GHook is active, which is normally the case
112
 * until the #GHook is destroyed.
113
 *
114
 * Returns: %TRUE if the #GHook is active
115
 */
116
117
/**
118
 * G_HOOK_IN_CALL:
119
 * @hook: a #GHook
120
 *
121
 * Returns %TRUE if the #GHook function is currently executing.
122
 *
123
 * Returns: %TRUE if the #GHook function is currently executing
124
 */
125
126
/**
127
 * G_HOOK_IS_UNLINKED:
128
 * @hook: a #GHook
129
 *
130
 * Returns %TRUE if the #GHook is not in a #GHookList.
131
 *
132
 * Returns: %TRUE if the #GHook is not in a #GHookList
133
 */
134
135
/**
136
 * GHook:
137
 * @data: data which is passed to func when this hook is invoked
138
 * @next: pointer to the next hook in the list
139
 * @prev: pointer to the previous hook in the list
140
 * @ref_count: the reference count of this hook
141
 * @hook_id: the id of this hook, which is unique within its list
142
 * @flags: flags which are set for this hook. See #GHookFlagMask for
143
 *     predefined flags
144
 * @func: the function to call when this hook is invoked. The possible
145
 *     signatures for this function are #GHookFunc and #GHookCheckFunc
146
 * @destroy: the default @finalize_hook function of a #GHookList calls
147
 *     this member of the hook that is being finalized
148
 *
149
 * The #GHook struct represents a single hook function in a #GHookList.
150
 */
151
152
/**
153
 * GHookFunc:
154
 * @data: the data field of the #GHook is passed to the hook function here
155
 *
156
 * Defines the type of a hook function that can be invoked
157
 * by g_hook_list_invoke().
158
 */
159
160
/**
161
 * GHookCheckFunc:
162
 * @data: the data field of the #GHook is passed to the hook function here
163
 *
164
 * Defines the type of a hook function that can be invoked
165
 * by g_hook_list_invoke_check().
166
 *
167
 * Returns: %FALSE if the #GHook should be destroyed
168
 */
169
170
/* --- functions --- */
171
static void
172
default_finalize_hook (GHookList *hook_list,
173
           GHook     *hook)
174
0
{
175
0
  GDestroyNotify destroy = hook->destroy;
176
177
0
  if (destroy)
178
0
    {
179
0
      hook->destroy = NULL;
180
0
      destroy (hook->data);
181
0
    }
182
0
}
183
184
/**
185
 * g_hook_list_init:
186
 * @hook_list: a #GHookList
187
 * @hook_size: the size of each element in the #GHookList,
188
 *     typically `sizeof (GHook)`.
189
 *
190
 * Initializes a #GHookList.
191
 * This must be called before the #GHookList is used.
192
 */
193
void
194
g_hook_list_init (GHookList *hook_list,
195
      guint      hook_size)
196
0
{
197
0
  g_return_if_fail (hook_list != NULL);
198
0
  g_return_if_fail (hook_size >= sizeof (GHook));
199
  
200
0
  hook_list->seq_id = 1;
201
0
  hook_list->hook_size = hook_size;
202
0
  hook_list->is_setup = TRUE;
203
0
  hook_list->hooks = NULL;
204
0
  hook_list->dummy3 = NULL;
205
0
  hook_list->finalize_hook = default_finalize_hook;
206
0
  hook_list->dummy[0] = NULL;
207
0
  hook_list->dummy[1] = NULL;
208
0
}
209
210
/**
211
 * g_hook_list_clear:
212
 * @hook_list: a #GHookList
213
 *
214
 * Removes all the #GHook elements from a #GHookList.
215
 */
216
void
217
g_hook_list_clear (GHookList *hook_list)
218
0
{
219
0
  g_return_if_fail (hook_list != NULL);
220
  
221
0
  if (hook_list->is_setup)
222
0
    {
223
0
      GHook *hook;
224
      
225
0
      hook_list->is_setup = FALSE;
226
      
227
0
      hook = hook_list->hooks;
228
0
      if (!hook)
229
0
  {
230
    /* destroy hook_list->hook_memchunk */
231
0
  }
232
0
      else
233
0
  do
234
0
    {
235
0
      GHook *tmp;
236
      
237
0
      g_hook_ref (hook_list, hook);
238
0
      g_hook_destroy_link (hook_list, hook);
239
0
      tmp = hook->next;
240
0
      g_hook_unref (hook_list, hook);
241
0
      hook = tmp;
242
0
    }
243
0
  while (hook);
244
0
    }
245
0
}
246
247
/**
248
 * g_hook_alloc:
249
 * @hook_list: a #GHookList
250
 *
251
 * Allocates space for a #GHook and initializes it.
252
 *
253
 * Returns: a new #GHook
254
 */
255
GHook*
256
g_hook_alloc (GHookList *hook_list)
257
0
{
258
0
  GHook *hook;
259
  
260
0
  g_return_val_if_fail (hook_list != NULL, NULL);
261
0
  g_return_val_if_fail (hook_list->is_setup, NULL);
262
  
263
0
  hook = g_slice_alloc0 (hook_list->hook_size);
264
0
  hook->data = NULL;
265
0
  hook->next = NULL;
266
0
  hook->prev = NULL;
267
0
  hook->flags = G_HOOK_FLAG_ACTIVE;
268
0
  hook->ref_count = 0;
269
0
  hook->hook_id = 0;
270
0
  hook->func = NULL;
271
0
  hook->destroy = NULL;
272
  
273
0
  return hook;
274
0
}
275
/**
276
 * g_hook_free:
277
 * @hook_list: a #GHookList
278
 * @hook: the #GHook to free
279
 *
280
 * Calls the #GHookList @finalize_hook function if it exists,
281
 * and frees the memory allocated for the #GHook.
282
 */
283
void
284
g_hook_free (GHookList *hook_list,
285
       GHook     *hook)
286
0
{
287
0
  g_return_if_fail (hook_list != NULL);
288
0
  g_return_if_fail (hook_list->is_setup);
289
0
  g_return_if_fail (hook != NULL);
290
0
  g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
291
0
  g_return_if_fail (!G_HOOK_IN_CALL (hook));
292
293
0
  if(hook_list->finalize_hook != NULL)
294
0
      hook_list->finalize_hook (hook_list, hook);
295
0
  g_slice_free1 (hook_list->hook_size, hook);
296
0
}
297
298
/**
299
 * g_hook_destroy_link:
300
 * @hook_list: a #GHookList
301
 * @hook: the #GHook to remove
302
 *
303
 * Removes one #GHook from a #GHookList, marking it
304
 * inactive and calling g_hook_unref() on it.
305
 */
306
void
307
g_hook_destroy_link (GHookList *hook_list,
308
         GHook     *hook)
309
0
{
310
0
  g_return_if_fail (hook_list != NULL);
311
0
  g_return_if_fail (hook != NULL);
312
313
0
  hook->flags &= ~G_HOOK_FLAG_ACTIVE;
314
0
  if (hook->hook_id)
315
0
    {
316
0
      hook->hook_id = 0;
317
0
      g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
318
0
    }
319
0
}
320
321
/**
322
 * g_hook_destroy:
323
 * @hook_list: a #GHookList
324
 * @hook_id: a hook ID
325
 *
326
 * Destroys a #GHook, given its ID.
327
 *
328
 * Returns: %TRUE if the #GHook was found in the #GHookList and destroyed
329
 */
330
gboolean
331
g_hook_destroy (GHookList   *hook_list,
332
    gulong       hook_id)
333
0
{
334
0
  GHook *hook;
335
  
336
0
  g_return_val_if_fail (hook_list != NULL, FALSE);
337
0
  g_return_val_if_fail (hook_id > 0, FALSE);
338
  
339
0
  hook = g_hook_get (hook_list, hook_id);
340
0
  if (hook)
341
0
    {
342
0
      g_hook_destroy_link (hook_list, hook);
343
0
      return TRUE;
344
0
    }
345
  
346
0
  return FALSE;
347
0
}
348
349
/**
350
 * g_hook_unref:
351
 * @hook_list: a #GHookList
352
 * @hook: the #GHook to unref
353
 *
354
 * Decrements the reference count of a #GHook.
355
 * If the reference count falls to 0, the #GHook is removed
356
 * from the #GHookList and g_hook_free() is called to free it.
357
 */
358
void
359
g_hook_unref (GHookList *hook_list,
360
        GHook *hook)
361
0
{
362
0
  g_return_if_fail (hook_list != NULL);
363
0
  g_return_if_fail (hook != NULL);
364
0
  g_return_if_fail (hook->ref_count > 0);
365
  
366
0
  hook->ref_count--;
367
0
  if (!hook->ref_count)
368
0
    {
369
0
      g_return_if_fail (hook->hook_id == 0);
370
0
      g_return_if_fail (!G_HOOK_IN_CALL (hook));
371
372
0
      if (hook->prev)
373
0
  hook->prev->next = hook->next;
374
0
      else
375
0
  hook_list->hooks = hook->next;
376
0
      if (hook->next)
377
0
  {
378
0
    hook->next->prev = hook->prev;
379
0
    hook->next = NULL;
380
0
  }
381
0
      hook->prev = NULL;
382
383
0
      if (!hook_list->is_setup)
384
0
  {
385
0
    hook_list->is_setup = TRUE;
386
0
    g_hook_free (hook_list, hook);
387
0
    hook_list->is_setup = FALSE;
388
      
389
0
    if (!hook_list->hooks)
390
0
      {
391
        /* destroy hook_list->hook_memchunk */
392
0
      }
393
0
  }
394
0
      else
395
0
  g_hook_free (hook_list, hook);
396
0
    }
397
0
}
398
399
/**
400
 * g_hook_ref:
401
 * @hook_list: a #GHookList
402
 * @hook: the #GHook to increment the reference count of
403
 *
404
 * Increments the reference count for a #GHook.
405
 *
406
 * Returns: the @hook that was passed in (since 2.6)
407
 */
408
GHook *
409
g_hook_ref (GHookList *hook_list,
410
      GHook     *hook)
411
0
{
412
0
  g_return_val_if_fail (hook_list != NULL, NULL);
413
0
  g_return_val_if_fail (hook != NULL, NULL);
414
0
  g_return_val_if_fail (hook->ref_count > 0, NULL);
415
  
416
0
  hook->ref_count++;
417
418
0
  return hook;
419
0
}
420
421
/**
422
 * g_hook_append:
423
 * @hook_list: a #GHookList
424
 * @hook: the #GHook to add to the end of @hook_list
425
 *
426
 * Appends a #GHook onto the end of a #GHookList.
427
 */
428
429
/**
430
 * g_hook_prepend:
431
 * @hook_list: a #GHookList
432
 * @hook: the #GHook to add to the start of @hook_list
433
 *
434
 * Prepends a #GHook on the start of a #GHookList.
435
 */
436
void
437
g_hook_prepend (GHookList *hook_list,
438
    GHook   *hook)
439
0
{
440
0
  g_return_if_fail (hook_list != NULL);
441
  
442
0
  g_hook_insert_before (hook_list, hook_list->hooks, hook);
443
0
}
444
445
/**
446
 * g_hook_insert_before:
447
 * @hook_list: a #GHookList
448
 * @sibling: (nullable): the #GHook to insert the new #GHook before
449
 * @hook: the #GHook to insert
450
 *
451
 * Inserts a #GHook into a #GHookList, before a given #GHook.
452
 */
453
void
454
g_hook_insert_before (GHookList *hook_list,
455
          GHook *sibling,
456
          GHook *hook)
457
0
{
458
0
  g_return_if_fail (hook_list != NULL);
459
0
  g_return_if_fail (hook_list->is_setup);
460
0
  g_return_if_fail (hook != NULL);
461
0
  g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
462
0
  g_return_if_fail (hook->ref_count == 0);
463
  
464
0
  hook->hook_id = hook_list->seq_id++;
465
0
  hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
466
  
467
0
  if (sibling)
468
0
    {
469
0
      if (sibling->prev)
470
0
  {
471
0
    hook->prev = sibling->prev;
472
0
    hook->prev->next = hook;
473
0
    hook->next = sibling;
474
0
    sibling->prev = hook;
475
0
  }
476
0
      else
477
0
  {
478
0
    hook_list->hooks = hook;
479
0
    hook->next = sibling;
480
0
    sibling->prev = hook;
481
0
  }
482
0
    }
483
0
  else
484
0
    {
485
0
      if (hook_list->hooks)
486
0
  {
487
0
    sibling = hook_list->hooks;
488
0
    while (sibling->next)
489
0
      sibling = sibling->next;
490
0
    hook->prev = sibling;
491
0
    sibling->next = hook;
492
0
  }
493
0
      else
494
0
  hook_list->hooks = hook;
495
0
    }
496
0
}
497
498
/**
499
 * g_hook_list_invoke:
500
 * @hook_list: a #GHookList
501
 * @may_recurse: %TRUE if functions which are already running
502
 *     (e.g. in another thread) can be called. If set to %FALSE,
503
 *     these are skipped
504
 *
505
 * Calls all of the #GHook functions in a #GHookList.
506
 */
507
void
508
g_hook_list_invoke (GHookList *hook_list,
509
        gboolean   may_recurse)
510
0
{
511
0
  GHook *hook;
512
  
513
0
  g_return_if_fail (hook_list != NULL);
514
0
  g_return_if_fail (hook_list->is_setup);
515
516
0
  hook = g_hook_first_valid (hook_list, may_recurse);
517
0
  while (hook)
518
0
    {
519
0
      GHookFunc func;
520
0
      gboolean was_in_call;
521
      
522
0
      func = (GHookFunc) hook->func;
523
      
524
0
      was_in_call = G_HOOK_IN_CALL (hook);
525
0
      hook->flags |= G_HOOK_FLAG_IN_CALL;
526
0
      func (hook->data);
527
0
      if (!was_in_call)
528
0
  hook->flags &= ~G_HOOK_FLAG_IN_CALL;
529
      
530
0
      hook = g_hook_next_valid (hook_list, hook, may_recurse);
531
0
    }
532
0
}
533
534
/**
535
 * g_hook_list_invoke_check:
536
 * @hook_list: a #GHookList
537
 * @may_recurse: %TRUE if functions which are already running
538
 *     (e.g. in another thread) can be called. If set to %FALSE,
539
 *     these are skipped
540
 *
541
 * Calls all of the #GHook functions in a #GHookList.
542
 * Any function which returns %FALSE is removed from the #GHookList.
543
 */
544
void
545
g_hook_list_invoke_check (GHookList *hook_list,
546
        gboolean   may_recurse)
547
0
{
548
0
  GHook *hook;
549
  
550
0
  g_return_if_fail (hook_list != NULL);
551
0
  g_return_if_fail (hook_list->is_setup);
552
  
553
0
  hook = g_hook_first_valid (hook_list, may_recurse);
554
0
  while (hook)
555
0
    {
556
0
      GHookCheckFunc func;
557
0
      gboolean was_in_call;
558
0
      gboolean need_destroy;
559
      
560
0
      func = (GHookCheckFunc) hook->func;
561
      
562
0
      was_in_call = G_HOOK_IN_CALL (hook);
563
0
      hook->flags |= G_HOOK_FLAG_IN_CALL;
564
0
      need_destroy = !func (hook->data);
565
0
      if (!was_in_call)
566
0
  hook->flags &= ~G_HOOK_FLAG_IN_CALL;
567
0
      if (need_destroy)
568
0
  g_hook_destroy_link (hook_list, hook);
569
      
570
0
      hook = g_hook_next_valid (hook_list, hook, may_recurse);
571
0
    }
572
0
}
573
574
/**
575
 * GHookCheckMarshaller:
576
 * @hook: a #GHook
577
 * @marshal_data: user data
578
 *
579
 * Defines the type of function used by g_hook_list_marshal_check().
580
 *
581
 * Returns: %FALSE if @hook should be destroyed
582
 */
583
584
/**
585
 * g_hook_list_marshal_check:
586
 * @hook_list: a #GHookList
587
 * @may_recurse: %TRUE if hooks which are currently running
588
 *     (e.g. in another thread) are considered valid. If set to %FALSE,
589
 *     these are skipped
590
 * @marshaller: (scope call): the function to call for each #GHook
591
 * @marshal_data: data to pass to @marshaller
592
 *
593
 * Calls a function on each valid #GHook and destroys it if the
594
 * function returns %FALSE.
595
 */
596
void
597
g_hook_list_marshal_check (GHookList         *hook_list,
598
         gboolean   may_recurse,
599
         GHookCheckMarshaller marshaller,
600
         gpointer   data)
601
0
{
602
0
  GHook *hook;
603
  
604
0
  g_return_if_fail (hook_list != NULL);
605
0
  g_return_if_fail (hook_list->is_setup);
606
0
  g_return_if_fail (marshaller != NULL);
607
  
608
0
  hook = g_hook_first_valid (hook_list, may_recurse);
609
0
  while (hook)
610
0
    {
611
0
      gboolean was_in_call;
612
0
      gboolean need_destroy;
613
      
614
0
      was_in_call = G_HOOK_IN_CALL (hook);
615
0
      hook->flags |= G_HOOK_FLAG_IN_CALL;
616
0
      need_destroy = !marshaller (hook, data);
617
0
      if (!was_in_call)
618
0
  hook->flags &= ~G_HOOK_FLAG_IN_CALL;
619
0
      if (need_destroy)
620
0
  g_hook_destroy_link (hook_list, hook);
621
      
622
0
      hook = g_hook_next_valid (hook_list, hook, may_recurse);
623
0
    }
624
0
}
625
626
/**
627
 * GHookMarshaller:
628
 * @hook: a #GHook
629
 * @marshal_data: user data
630
 *
631
 * Defines the type of function used by g_hook_list_marshal().
632
 */
633
634
/**
635
 * g_hook_list_marshal:
636
 * @hook_list: a #GHookList
637
 * @may_recurse: %TRUE if hooks which are currently running
638
 *     (e.g. in another thread) are considered valid. If set to %FALSE,
639
 *     these are skipped
640
 * @marshaller: (scope call): the function to call for each #GHook
641
 * @marshal_data: data to pass to @marshaller
642
 *
643
 * Calls a function on each valid #GHook.
644
 */
645
void
646
g_hook_list_marshal (GHookList         *hook_list,
647
         gboolean         may_recurse,
648
         GHookMarshaller        marshaller,
649
         gpointer         data)
650
0
{
651
0
  GHook *hook;
652
  
653
0
  g_return_if_fail (hook_list != NULL);
654
0
  g_return_if_fail (hook_list->is_setup);
655
0
  g_return_if_fail (marshaller != NULL);
656
  
657
0
  hook = g_hook_first_valid (hook_list, may_recurse);
658
0
  while (hook)
659
0
    {
660
0
      gboolean was_in_call;
661
      
662
0
      was_in_call = G_HOOK_IN_CALL (hook);
663
0
      hook->flags |= G_HOOK_FLAG_IN_CALL;
664
0
      marshaller (hook, data);
665
0
      if (!was_in_call)
666
0
  hook->flags &= ~G_HOOK_FLAG_IN_CALL;
667
      
668
0
      hook = g_hook_next_valid (hook_list, hook, may_recurse);
669
0
    }
670
0
}
671
672
/**
673
 * g_hook_first_valid:
674
 * @hook_list: a #GHookList
675
 * @may_be_in_call: %TRUE if hooks which are currently running
676
 *     (e.g. in another thread) are considered valid. If set to %FALSE,
677
 *     these are skipped
678
 *
679
 * Returns the first #GHook in a #GHookList which has not been destroyed.
680
 * The reference count for the #GHook is incremented, so you must call
681
 * g_hook_unref() to restore it when no longer needed. (Or call
682
 * g_hook_next_valid() if you are stepping through the #GHookList.)
683
 *
684
 * Returns: the first valid #GHook, or %NULL if none are valid
685
 */
686
GHook*
687
g_hook_first_valid (GHookList *hook_list,
688
        gboolean   may_be_in_call)
689
0
{
690
0
  g_return_val_if_fail (hook_list != NULL, NULL);
691
  
692
0
  if (hook_list->is_setup)
693
0
    {
694
0
      GHook *hook;
695
      
696
0
      hook = hook_list->hooks;
697
0
      if (hook)
698
0
  {
699
0
    g_hook_ref (hook_list, hook);
700
0
    if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
701
0
      return hook;
702
0
    else
703
0
      return g_hook_next_valid (hook_list, hook, may_be_in_call);
704
0
  }
705
0
    }
706
  
707
0
  return NULL;
708
0
}
709
710
/**
711
 * g_hook_next_valid:
712
 * @hook_list: a #GHookList
713
 * @hook: the current #GHook
714
 * @may_be_in_call: %TRUE if hooks which are currently running
715
 *     (e.g. in another thread) are considered valid. If set to %FALSE,
716
 *     these are skipped
717
 *
718
 * Returns the next #GHook in a #GHookList which has not been destroyed.
719
 * The reference count for the #GHook is incremented, so you must call
720
 * g_hook_unref() to restore it when no longer needed. (Or continue to call
721
 * g_hook_next_valid() until %NULL is returned.)
722
 *
723
 * Returns: the next valid #GHook, or %NULL if none are valid
724
 */
725
GHook*
726
g_hook_next_valid (GHookList *hook_list,
727
       GHook     *hook,
728
       gboolean   may_be_in_call)
729
0
{
730
0
  GHook *ohook = hook;
731
732
0
  g_return_val_if_fail (hook_list != NULL, NULL);
733
734
0
  if (!hook)
735
0
    return NULL;
736
  
737
0
  hook = hook->next;
738
0
  while (hook)
739
0
    {
740
0
      if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
741
0
  {
742
0
    g_hook_ref (hook_list, hook);
743
0
    g_hook_unref (hook_list, ohook);
744
    
745
0
    return hook;
746
0
  }
747
0
      hook = hook->next;
748
0
    }
749
0
  g_hook_unref (hook_list, ohook);
750
751
0
  return NULL;
752
0
}
753
754
/**
755
 * g_hook_get:
756
 * @hook_list: a #GHookList
757
 * @hook_id: a hook id
758
 *
759
 * Returns the #GHook with the given id, or %NULL if it is not found.
760
 *
761
 * Returns: the #GHook with the given id, or %NULL if it is not found
762
 */
763
GHook*
764
g_hook_get (GHookList *hook_list,
765
      gulong     hook_id)
766
0
{
767
0
  GHook *hook;
768
  
769
0
  g_return_val_if_fail (hook_list != NULL, NULL);
770
0
  g_return_val_if_fail (hook_id > 0, NULL);
771
  
772
0
  hook = hook_list->hooks;
773
0
  while (hook)
774
0
    {
775
0
      if (hook->hook_id == hook_id)
776
0
  return hook;
777
0
      hook = hook->next;
778
0
    }
779
  
780
0
  return NULL;
781
0
}
782
783
/**
784
 * GHookFindFunc:
785
 * @hook: a #GHook
786
 * @data: user data passed to g_hook_find_func()
787
 *
788
 * Defines the type of the function passed to g_hook_find().
789
 *
790
 * Returns: %TRUE if the required #GHook has been found
791
 */
792
793
/**
794
 * g_hook_find:
795
 * @hook_list: a #GHookList
796
 * @need_valids: %TRUE if #GHook elements which have been destroyed
797
 *     should be skipped
798
 * @func: (scope call): the function to call for each #GHook, which should return
799
 *     %TRUE when the #GHook has been found
800
 * @data: the data to pass to @func
801
 *
802
 * Finds a #GHook in a #GHookList using the given function to
803
 * test for a match.
804
 *
805
 * Returns: the found #GHook or %NULL if no matching #GHook is found
806
 */
807
GHook*
808
g_hook_find (GHookList    *hook_list,
809
       gboolean    need_valids,
810
       GHookFindFunc func,
811
       gpointer    data)
812
0
{
813
0
  GHook *hook;
814
  
815
0
  g_return_val_if_fail (hook_list != NULL, NULL);
816
0
  g_return_val_if_fail (func != NULL, NULL);
817
  
818
0
  hook = hook_list->hooks;
819
0
  while (hook)
820
0
    {
821
0
      GHook *tmp;
822
823
      /* test only non-destroyed hooks */
824
0
      if (!hook->hook_id)
825
0
  {
826
0
    hook = hook->next;
827
0
    continue;
828
0
  }
829
      
830
0
      g_hook_ref (hook_list, hook);
831
      
832
0
      if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
833
0
  {
834
0
    g_hook_unref (hook_list, hook);
835
    
836
0
    return hook;
837
0
  }
838
839
0
      tmp = hook->next;
840
0
      g_hook_unref (hook_list, hook);
841
0
      hook = tmp;
842
0
    }
843
  
844
0
  return NULL;
845
0
}
846
847
/**
848
 * g_hook_find_data:
849
 * @hook_list: a #GHookList
850
 * @need_valids: %TRUE if #GHook elements which have been destroyed
851
 *     should be skipped
852
 * @data: the data to find
853
 *
854
 * Finds a #GHook in a #GHookList with the given data.
855
 *
856
 * Returns: the #GHook with the given @data or %NULL if no matching
857
 *     #GHook is found
858
 */
859
GHook*
860
g_hook_find_data (GHookList *hook_list,
861
      gboolean   need_valids,
862
      gpointer   data)
863
0
{
864
0
  GHook *hook;
865
  
866
0
  g_return_val_if_fail (hook_list != NULL, NULL);
867
  
868
0
  hook = hook_list->hooks;
869
0
  while (hook)
870
0
    {
871
      /* test only non-destroyed hooks */
872
0
      if (hook->data == data &&
873
0
    hook->hook_id &&
874
0
    (!need_valids || G_HOOK_ACTIVE (hook)))
875
0
  return hook;
876
877
0
      hook = hook->next;
878
0
    }
879
  
880
0
  return NULL;
881
0
}
882
883
/**
884
 * g_hook_find_func:
885
 * @hook_list: a #GHookList
886
 * @need_valids: %TRUE if #GHook elements which have been destroyed
887
 *     should be skipped
888
 * @func: the function to find
889
 *
890
 * Finds a #GHook in a #GHookList with the given function.
891
 *
892
 * Returns: the #GHook with the given @func or %NULL if no matching
893
 *     #GHook is found
894
 */
895
GHook*
896
g_hook_find_func (GHookList *hook_list,
897
      gboolean   need_valids,
898
      gpointer   func)
899
0
{
900
0
  GHook *hook;
901
  
902
0
  g_return_val_if_fail (hook_list != NULL, NULL);
903
0
  g_return_val_if_fail (func != NULL, NULL);
904
  
905
0
  hook = hook_list->hooks;
906
0
  while (hook)
907
0
    {
908
      /* test only non-destroyed hooks */
909
0
      if (hook->func == func &&
910
0
    hook->hook_id &&
911
0
    (!need_valids || G_HOOK_ACTIVE (hook)))
912
0
  return hook;
913
914
0
      hook = hook->next;
915
0
    }
916
  
917
0
  return NULL;
918
0
}
919
920
/**
921
 * g_hook_find_func_data:
922
 * @hook_list: a #GHookList
923
 * @need_valids: %TRUE if #GHook elements which have been destroyed
924
 *     should be skipped
925
 * @func: (not nullable): the function to find
926
 * @data: the data to find
927
 *
928
 * Finds a #GHook in a #GHookList with the given function and data.
929
 *
930
 * Returns: the #GHook with the given @func and @data or %NULL if
931
 *     no matching #GHook is found
932
 */
933
GHook*
934
g_hook_find_func_data (GHookList *hook_list,
935
           gboolean   need_valids,
936
           gpointer   func,
937
           gpointer   data)
938
0
{
939
0
  GHook *hook;
940
  
941
0
  g_return_val_if_fail (hook_list != NULL, NULL);
942
0
  g_return_val_if_fail (func != NULL, NULL);
943
  
944
0
  hook = hook_list->hooks;
945
0
  while (hook)
946
0
    {
947
      /* test only non-destroyed hooks */
948
0
      if (hook->data == data &&
949
0
    hook->func == func &&
950
0
    hook->hook_id &&
951
0
    (!need_valids || G_HOOK_ACTIVE (hook)))
952
0
  return hook;
953
954
0
      hook = hook->next;
955
0
    }
956
  
957
0
  return NULL;
958
0
}
959
960
/**
961
 * GHookCompareFunc:
962
 * @new_hook: the #GHook being inserted
963
 * @sibling: the #GHook to compare with @new_hook
964
 *
965
 * Defines the type of function used to compare #GHook elements in
966
 * g_hook_insert_sorted().
967
 *
968
 * Returns: a value <= 0 if @new_hook should be before @sibling
969
 */
970
971
/**
972
 * g_hook_insert_sorted:
973
 * @hook_list: a #GHookList
974
 * @hook: the #GHook to insert
975
 * @func: (scope call): the comparison function used to sort the #GHook elements
976
 *
977
 * Inserts a #GHook into a #GHookList, sorted by the given function.
978
 */
979
void
980
g_hook_insert_sorted (GHookList       *hook_list,
981
          GHook       *hook,
982
          GHookCompareFunc func)
983
0
{
984
0
  GHook *sibling;
985
  
986
0
  g_return_if_fail (hook_list != NULL);
987
0
  g_return_if_fail (hook_list->is_setup);
988
0
  g_return_if_fail (hook != NULL);
989
0
  g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
990
0
  g_return_if_fail (hook->func != NULL);
991
0
  g_return_if_fail (func != NULL);
992
993
  /* first non-destroyed hook */
994
0
  sibling = hook_list->hooks;
995
0
  while (sibling && !sibling->hook_id)
996
0
    sibling = sibling->next;
997
  
998
0
  while (sibling)
999
0
    {
1000
0
      GHook *tmp;
1001
      
1002
0
      g_hook_ref (hook_list, sibling);
1003
0
      if (func (hook, sibling) <= 0 && sibling->hook_id)
1004
0
  {
1005
0
    g_hook_unref (hook_list, sibling);
1006
0
    break;
1007
0
  }
1008
1009
      /* next non-destroyed hook */
1010
0
      tmp = sibling->next;
1011
0
      while (tmp && !tmp->hook_id)
1012
0
  tmp = tmp->next;
1013
1014
0
      g_hook_unref (hook_list, sibling);
1015
0
      sibling = tmp;
1016
   
1017
0
 }
1018
  
1019
0
  g_hook_insert_before (hook_list, sibling, hook);
1020
0
}
1021
1022
/**
1023
 * g_hook_compare_ids:
1024
 * @new_hook: a #GHook
1025
 * @sibling: a #GHook to compare with @new_hook
1026
 *
1027
 * Compares the ids of two #GHook elements, returning a negative value
1028
 * if the second id is greater than the first.
1029
 *
1030
 * Returns: a value <= 0 if the id of @sibling is >= the id of @new_hook
1031
 */
1032
gint
1033
g_hook_compare_ids (GHook *new_hook,
1034
        GHook *sibling)
1035
0
{
1036
0
  if (new_hook->hook_id < sibling->hook_id)
1037
0
    return -1;
1038
0
  else if (new_hook->hook_id > sibling->hook_id)
1039
0
    return 1;
1040
  
1041
0
  return 0;
1042
0
}