Coverage Report

Created: 2025-07-18 06:10

/src/tinysparql/subprojects/glib-2.80.3/glib/gasyncqueue.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
 * GAsyncQueue: asynchronous queue implementation, based on GQueue.
5
 * Copyright (C) 2000 Sebastian Wilhelmi; University of Karlsruhe
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
 * MT safe
25
 */
26
27
#include "config.h"
28
29
#include "gasyncqueue.h"
30
#include "gasyncqueueprivate.h"
31
32
#include "gmain.h"
33
#include "gmem.h"
34
#include "gqueue.h"
35
#include "gtestutils.h"
36
#include "gtimer.h"
37
#include "gthread.h"
38
#include "deprecated/gthread.h"
39
40
/**
41
 * GAsyncQueue:
42
 *
43
 * An opaque data structure which represents an asynchronous queue.
44
 *
45
 * It should only be accessed through the `g_async_queue_*` functions.
46
 */
47
struct _GAsyncQueue
48
{
49
  GMutex mutex;
50
  GCond cond;
51
  GQueue queue;
52
  GDestroyNotify item_free_func;
53
  guint waiting_threads;
54
  gint ref_count;
55
};
56
57
typedef struct
58
{
59
  GCompareDataFunc func;
60
  gpointer         user_data;
61
} SortData;
62
63
/**
64
 * g_async_queue_new: (constructor)
65
 *
66
 * Creates a new asynchronous queue.
67
 *
68
 * Returns: (transfer full): a new #GAsyncQueue. Free with g_async_queue_unref()
69
 */
70
GAsyncQueue *
71
g_async_queue_new (void)
72
8
{
73
8
  return g_async_queue_new_full (NULL);
74
8
}
75
76
/**
77
 * g_async_queue_new_full: (constructor)
78
 * @item_free_func: (nullable): function to free queue elements
79
 *
80
 * Creates a new asynchronous queue and sets up a destroy notify
81
 * function that is used to free any remaining queue items when
82
 * the queue is destroyed after the final unref.
83
 *
84
 * Returns: (transfer full): a new #GAsyncQueue. Free with g_async_queue_unref()
85
 *
86
 * Since: 2.16
87
 */
88
GAsyncQueue *
89
g_async_queue_new_full (GDestroyNotify item_free_func)
90
22.9k
{
91
22.9k
  GAsyncQueue *queue;
92
93
22.9k
  queue = g_new (GAsyncQueue, 1);
94
22.9k
  g_mutex_init (&queue->mutex);
95
22.9k
  g_cond_init (&queue->cond);
96
22.9k
  g_queue_init (&queue->queue);
97
22.9k
  queue->waiting_threads = 0;
98
22.9k
  queue->ref_count = 1;
99
22.9k
  queue->item_free_func = item_free_func;
100
101
22.9k
  return queue;
102
22.9k
}
103
104
/**
105
 * g_async_queue_ref:
106
 * @queue: a #GAsyncQueue
107
 *
108
 * Increases the reference count of the asynchronous @queue by 1.
109
 * You do not need to hold the lock to call this function.
110
 *
111
 * Returns: (transfer full): the @queue that was passed in (since 2.6)
112
 */
113
GAsyncQueue *
114
g_async_queue_ref (GAsyncQueue *queue)
115
0
{
116
0
  g_return_val_if_fail (queue, NULL);
117
118
0
  g_atomic_int_inc (&queue->ref_count);
119
120
0
  return queue;
121
0
}
122
123
/**
124
 * g_async_queue_ref_unlocked:
125
 * @queue: a #GAsyncQueue
126
 *
127
 * Increases the reference count of the asynchronous @queue by 1.
128
 *
129
 * Deprecated: 2.8: Reference counting is done atomically.
130
 * so g_async_queue_ref() can be used regardless of the @queue's
131
 * lock.
132
 */
133
void
134
g_async_queue_ref_unlocked (GAsyncQueue *queue)
135
0
{
136
0
  g_return_if_fail (queue);
137
138
0
  g_atomic_int_inc (&queue->ref_count);
139
0
}
140
141
/**
142
 * g_async_queue_unref_and_unlock:
143
 * @queue: a #GAsyncQueue
144
 *
145
 * Decreases the reference count of the asynchronous @queue by 1
146
 * and releases the lock. This function must be called while holding
147
 * the @queue's lock. If the reference count went to 0, the @queue
148
 * will be destroyed and the memory allocated will be freed.
149
 *
150
 * Deprecated: 2.8: Reference counting is done atomically.
151
 * so g_async_queue_unref() can be used regardless of the @queue's
152
 * lock.
153
 */
154
void
155
g_async_queue_unref_and_unlock (GAsyncQueue *queue)
156
0
{
157
0
  g_return_if_fail (queue);
158
159
0
  g_mutex_unlock (&queue->mutex);
160
0
  g_async_queue_unref (queue);
161
0
}
162
163
/**
164
 * g_async_queue_unref:
165
 * @queue: (transfer full): a #GAsyncQueue.
166
 *
167
 * Decreases the reference count of the asynchronous @queue by 1.
168
 *
169
 * If the reference count went to 0, the @queue will be destroyed
170
 * and the memory allocated will be freed. So you are not allowed
171
 * to use the @queue afterwards, as it might have disappeared.
172
 * You do not need to hold the lock to call this function.
173
 */
174
void
175
g_async_queue_unref (GAsyncQueue *queue)
176
22.9k
{
177
22.9k
  g_return_if_fail (queue);
178
179
22.9k
  if (g_atomic_int_dec_and_test (&queue->ref_count))
180
22.9k
    {
181
22.9k
      g_return_if_fail (queue->waiting_threads == 0);
182
22.9k
      g_mutex_clear (&queue->mutex);
183
22.9k
      g_cond_clear (&queue->cond);
184
22.9k
      if (queue->item_free_func)
185
7.65k
        g_queue_foreach (&queue->queue, (GFunc) queue->item_free_func, NULL);
186
22.9k
      g_queue_clear (&queue->queue);
187
22.9k
      g_free (queue);
188
22.9k
    }
189
22.9k
}
190
191
/**
192
 * g_async_queue_lock:
193
 * @queue: a #GAsyncQueue
194
 *
195
 * Acquires the @queue's lock. If another thread is already
196
 * holding the lock, this call will block until the lock
197
 * becomes available.
198
 *
199
 * Call g_async_queue_unlock() to drop the lock again.
200
 *
201
 * While holding the lock, you can only call the
202
 * g_async_queue_*_unlocked() functions on @queue. Otherwise,
203
 * deadlock may occur.
204
 */
205
void
206
g_async_queue_lock (GAsyncQueue *queue)
207
45.9k
{
208
45.9k
  g_return_if_fail (queue);
209
210
45.9k
  g_mutex_lock (&queue->mutex);
211
45.9k
}
212
213
/**
214
 * g_async_queue_unlock:
215
 * @queue: a #GAsyncQueue
216
 *
217
 * Releases the queue's lock.
218
 *
219
 * Calling this function when you have not acquired
220
 * the with g_async_queue_lock() leads to undefined
221
 * behaviour.
222
 */
223
void
224
g_async_queue_unlock (GAsyncQueue *queue)
225
45.9k
{
226
45.9k
  g_return_if_fail (queue);
227
228
45.9k
  g_mutex_unlock (&queue->mutex);
229
45.9k
}
230
231
/**
232
 * g_async_queue_push:
233
 * @queue: a #GAsyncQueue
234
 * @data: (not nullable): data to push onto the @queue
235
 *
236
 * Pushes the @data into the @queue.
237
 *
238
 * The @data parameter must not be %NULL.
239
 */
240
void
241
g_async_queue_push (GAsyncQueue *queue,
242
                    gpointer     data)
243
0
{
244
0
  g_return_if_fail (queue);
245
0
  g_return_if_fail (data);
246
247
0
  g_mutex_lock (&queue->mutex);
248
0
  g_async_queue_push_unlocked (queue, data);
249
0
  g_mutex_unlock (&queue->mutex);
250
0
}
251
252
/**
253
 * g_async_queue_push_unlocked:
254
 * @queue: a #GAsyncQueue
255
 * @data: (not nullable): data to push onto the @queue
256
 *
257
 * Pushes the @data into the @queue.
258
 *
259
 * The @data parameter must not be %NULL.
260
 *
261
 * This function must be called while holding the @queue's lock.
262
 */
263
void
264
g_async_queue_push_unlocked (GAsyncQueue *queue,
265
                             gpointer     data)
266
15.3k
{
267
15.3k
  g_return_if_fail (queue);
268
15.3k
  g_return_if_fail (data);
269
270
15.3k
  g_queue_push_head (&queue->queue, data);
271
15.3k
  if (queue->waiting_threads > 0)
272
15.3k
    g_cond_signal (&queue->cond);
273
15.3k
}
274
275
/**
276
 * g_async_queue_push_sorted:
277
 * @queue: a #GAsyncQueue
278
 * @data: (not nullable): the @data to push into the @queue
279
 * @func: (scope call): the #GCompareDataFunc is used to sort @queue
280
 * @user_data: user data passed to @func.
281
 *
282
 * Inserts @data into @queue using @func to determine the new
283
 * position.
284
 *
285
 * This function requires that the @queue is sorted before pushing on
286
 * new elements, see g_async_queue_sort().
287
 *
288
 * This function will lock @queue before it sorts the queue and unlock
289
 * it when it is finished.
290
 *
291
 * For an example of @func see g_async_queue_sort().
292
 *
293
 * Since: 2.10
294
 */
295
void
296
g_async_queue_push_sorted (GAsyncQueue      *queue,
297
                           gpointer          data,
298
                           GCompareDataFunc  func,
299
                           gpointer          user_data)
300
0
{
301
0
  g_return_if_fail (queue != NULL);
302
303
0
  g_mutex_lock (&queue->mutex);
304
0
  g_async_queue_push_sorted_unlocked (queue, data, func, user_data);
305
0
  g_mutex_unlock (&queue->mutex);
306
0
}
307
308
static gint
309
g_async_queue_invert_compare (gpointer  v1,
310
                              gpointer  v2,
311
                              SortData *sd)
312
0
{
313
0
  return -sd->func (v1, v2, sd->user_data);
314
0
}
315
316
/**
317
 * g_async_queue_push_sorted_unlocked:
318
 * @queue: a #GAsyncQueue
319
 * @data: the data to push into the @queue
320
 * @func: (scope call): the #GCompareDataFunc is used to sort @queue
321
 * @user_data: user data passed to @func.
322
 *
323
 * Inserts @data into @queue using @func to determine the new
324
 * position.
325
 *
326
 * The sort function @func is passed two elements of the @queue.
327
 * It should return 0 if they are equal, a negative value if the
328
 * first element should be higher in the @queue or a positive value
329
 * if the first element should be lower in the @queue than the second
330
 * element.
331
 *
332
 * This function requires that the @queue is sorted before pushing on
333
 * new elements, see g_async_queue_sort().
334
 *
335
 * This function must be called while holding the @queue's lock.
336
 *
337
 * For an example of @func see g_async_queue_sort().
338
 *
339
 * Since: 2.10
340
 */
341
void
342
g_async_queue_push_sorted_unlocked (GAsyncQueue      *queue,
343
                                    gpointer          data,
344
                                    GCompareDataFunc  func,
345
                                    gpointer          user_data)
346
0
{
347
0
  SortData sd;
348
349
0
  g_return_if_fail (queue != NULL);
350
351
0
  sd.func = func;
352
0
  sd.user_data = user_data;
353
354
0
  g_queue_insert_sorted (&queue->queue,
355
0
                         data,
356
0
                         (GCompareDataFunc)g_async_queue_invert_compare,
357
0
                         &sd);
358
0
  if (queue->waiting_threads > 0)
359
0
    g_cond_signal (&queue->cond);
360
0
}
361
362
static gpointer
363
g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
364
                                   gboolean     wait,
365
                                   gint64       end_time)
366
15.3k
{
367
15.3k
  gpointer retval;
368
369
15.3k
  if (!g_queue_peek_tail_link (&queue->queue) && wait)
370
15.3k
    {
371
15.3k
      queue->waiting_threads++;
372
30.6k
      while (!g_queue_peek_tail_link (&queue->queue))
373
15.3k
        {
374
15.3k
    if (end_time == -1)
375
7.66k
      g_cond_wait (&queue->cond, &queue->mutex);
376
7.65k
    else
377
7.65k
      {
378
7.65k
        if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time))
379
0
    break;
380
7.65k
      }
381
15.3k
        }
382
15.3k
      queue->waiting_threads--;
383
15.3k
    }
384
385
15.3k
  retval = g_queue_pop_tail (&queue->queue);
386
387
15.3k
  g_assert (retval || !wait || end_time > 0);
388
389
15.3k
  return retval;
390
15.3k
}
391
392
/**
393
 * g_async_queue_pop:
394
 * @queue: a #GAsyncQueue
395
 *
396
 * Pops data from the @queue. If @queue is empty, this function
397
 * blocks until data becomes available.
398
 *
399
 * Returns: data from the queue
400
 */
401
gpointer
402
g_async_queue_pop (GAsyncQueue *queue)
403
0
{
404
0
  gpointer retval;
405
406
0
  g_return_val_if_fail (queue, NULL);
407
408
0
  g_mutex_lock (&queue->mutex);
409
0
  retval = g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
410
0
  g_mutex_unlock (&queue->mutex);
411
412
0
  return retval;
413
0
}
414
415
/**
416
 * g_async_queue_pop_unlocked:
417
 * @queue: a #GAsyncQueue
418
 *
419
 * Pops data from the @queue. If @queue is empty, this function
420
 * blocks until data becomes available.
421
 *
422
 * This function must be called while holding the @queue's lock.
423
 *
424
 * Returns: data from the queue.
425
 */
426
gpointer
427
g_async_queue_pop_unlocked (GAsyncQueue *queue)
428
7.66k
{
429
7.66k
  g_return_val_if_fail (queue, NULL);
430
431
7.66k
  return g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
432
7.66k
}
433
434
/**
435
 * g_async_queue_try_pop:
436
 * @queue: a #GAsyncQueue
437
 *
438
 * Tries to pop data from the @queue. If no data is available,
439
 * %NULL is returned.
440
 *
441
 * Returns: (nullable): data from the queue or %NULL, when no data is
442
 *   available immediately.
443
 */
444
gpointer
445
g_async_queue_try_pop (GAsyncQueue *queue)
446
0
{
447
0
  gpointer retval;
448
449
0
  g_return_val_if_fail (queue, NULL);
450
451
0
  g_mutex_lock (&queue->mutex);
452
0
  retval = g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
453
0
  g_mutex_unlock (&queue->mutex);
454
455
0
  return retval;
456
0
}
457
458
/**
459
 * g_async_queue_try_pop_unlocked:
460
 * @queue: a #GAsyncQueue
461
 *
462
 * Tries to pop data from the @queue. If no data is available,
463
 * %NULL is returned.
464
 *
465
 * This function must be called while holding the @queue's lock.
466
 *
467
 * Returns: (nullable): data from the queue or %NULL, when no data is
468
 *   available immediately.
469
 */
470
gpointer
471
g_async_queue_try_pop_unlocked (GAsyncQueue *queue)
472
0
{
473
0
  g_return_val_if_fail (queue, NULL);
474
475
0
  return g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
476
0
}
477
478
/**
479
 * g_async_queue_timeout_pop:
480
 * @queue: a #GAsyncQueue
481
 * @timeout: the number of microseconds to wait
482
 *
483
 * Pops data from the @queue. If the queue is empty, blocks for
484
 * @timeout microseconds, or until data becomes available.
485
 *
486
 * If no data is received before the timeout, %NULL is returned.
487
 *
488
 * Returns: (nullable): data from the queue or %NULL, when no data is
489
 *   received before the timeout.
490
 */
491
gpointer
492
g_async_queue_timeout_pop (GAsyncQueue *queue,
493
         guint64      timeout)
494
7.65k
{
495
7.65k
  gint64 end_time = g_get_monotonic_time () + timeout;
496
7.65k
  gpointer retval;
497
498
7.65k
  g_return_val_if_fail (queue != NULL, NULL);
499
500
7.65k
  g_mutex_lock (&queue->mutex);
501
7.65k
  retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
502
7.65k
  g_mutex_unlock (&queue->mutex);
503
504
7.65k
  return retval;
505
7.65k
}
506
507
/**
508
 * g_async_queue_timeout_pop_unlocked:
509
 * @queue: a #GAsyncQueue
510
 * @timeout: the number of microseconds to wait
511
 *
512
 * Pops data from the @queue. If the queue is empty, blocks for
513
 * @timeout microseconds, or until data becomes available.
514
 *
515
 * If no data is received before the timeout, %NULL is returned.
516
 *
517
 * This function must be called while holding the @queue's lock.
518
 *
519
 * Returns: (nullable): data from the queue or %NULL, when no data is
520
 *   received before the timeout.
521
 */
522
gpointer
523
g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
524
            guint64      timeout)
525
0
{
526
0
  gint64 end_time = g_get_monotonic_time () + timeout;
527
528
0
  g_return_val_if_fail (queue != NULL, NULL);
529
530
0
  return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
531
0
}
532
533
/**
534
 * g_async_queue_timed_pop:
535
 * @queue: a #GAsyncQueue
536
 * @end_time: a #GTimeVal, determining the final time
537
 *
538
 * Pops data from the @queue. If the queue is empty, blocks until
539
 * @end_time or until data becomes available.
540
 *
541
 * If no data is received before @end_time, %NULL is returned.
542
 *
543
 * To easily calculate @end_time, a combination of g_get_real_time()
544
 * and g_time_val_add() can be used.
545
 *
546
 * Returns: (nullable): data from the queue or %NULL, when no data is
547
 *   received before @end_time.
548
 *
549
 * Deprecated: use g_async_queue_timeout_pop().
550
 */
551
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
552
gpointer
553
g_async_queue_timed_pop (GAsyncQueue *queue,
554
                         GTimeVal    *end_time)
555
0
{
556
0
  gint64 m_end_time;
557
0
  gpointer retval;
558
559
0
  g_return_val_if_fail (queue, NULL);
560
561
0
  if (end_time != NULL)
562
0
    {
563
0
      m_end_time = g_get_monotonic_time () +
564
0
        ((gint64) end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - g_get_real_time ());
565
0
    }
566
0
  else
567
0
    m_end_time = -1;
568
569
0
  g_mutex_lock (&queue->mutex);
570
0
  retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
571
0
  g_mutex_unlock (&queue->mutex);
572
573
0
  return retval;
574
0
}
575
G_GNUC_END_IGNORE_DEPRECATIONS
576
577
/**
578
 * g_async_queue_timed_pop_unlocked:
579
 * @queue: a #GAsyncQueue
580
 * @end_time: a #GTimeVal, determining the final time
581
 *
582
 * Pops data from the @queue. If the queue is empty, blocks until
583
 * @end_time or until data becomes available.
584
 *
585
 * If no data is received before @end_time, %NULL is returned.
586
 *
587
 * To easily calculate @end_time, a combination of g_get_real_time()
588
 * and g_time_val_add() can be used.
589
 *
590
 * This function must be called while holding the @queue's lock.
591
 *
592
 * Returns: (nullable): data from the queue or %NULL, when no data is
593
 *   received before @end_time.
594
 *
595
 * Deprecated: use g_async_queue_timeout_pop_unlocked().
596
 */
597
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
598
gpointer
599
g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
600
                                  GTimeVal    *end_time)
601
0
{
602
0
  gint64 m_end_time;
603
604
0
  g_return_val_if_fail (queue, NULL);
605
606
0
  if (end_time != NULL)
607
0
    {
608
0
      m_end_time = g_get_monotonic_time () +
609
0
        ((gint64) end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - g_get_real_time ());
610
0
    }
611
0
  else
612
0
    m_end_time = -1;
613
614
0
  return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
615
0
}
616
G_GNUC_END_IGNORE_DEPRECATIONS
617
618
/**
619
 * g_async_queue_length:
620
 * @queue: a #GAsyncQueue.
621
 *
622
 * Returns the length of the queue.
623
 *
624
 * Actually this function returns the number of data items in
625
 * the queue minus the number of waiting threads, so a negative
626
 * value means waiting threads, and a positive value means available
627
 * entries in the @queue. A return value of 0 could mean n entries
628
 * in the queue and n threads waiting. This can happen due to locking
629
 * of the queue or due to scheduling.
630
 *
631
 * Returns: the length of the @queue
632
 */
633
gint
634
g_async_queue_length (GAsyncQueue *queue)
635
0
{
636
0
  gint retval;
637
638
0
  g_return_val_if_fail (queue, 0);
639
640
0
  g_mutex_lock (&queue->mutex);
641
0
  retval = queue->queue.length - queue->waiting_threads;
642
0
  g_mutex_unlock (&queue->mutex);
643
644
0
  return retval;
645
0
}
646
647
/**
648
 * g_async_queue_length_unlocked:
649
 * @queue: a #GAsyncQueue
650
 *
651
 * Returns the length of the queue.
652
 *
653
 * Actually this function returns the number of data items in
654
 * the queue minus the number of waiting threads, so a negative
655
 * value means waiting threads, and a positive value means available
656
 * entries in the @queue. A return value of 0 could mean n entries
657
 * in the queue and n threads waiting. This can happen due to locking
658
 * of the queue or due to scheduling.
659
 *
660
 * This function must be called while holding the @queue's lock.
661
 *
662
 * Returns: the length of the @queue.
663
 */
664
gint
665
g_async_queue_length_unlocked (GAsyncQueue *queue)
666
38.2k
{
667
38.2k
  g_return_val_if_fail (queue, 0);
668
669
38.2k
  return queue->queue.length - queue->waiting_threads;
670
38.2k
}
671
672
/**
673
 * g_async_queue_sort:
674
 * @queue: a #GAsyncQueue
675
 * @func: (scope call): the #GCompareDataFunc is used to sort @queue
676
 * @user_data: user data passed to @func
677
 *
678
 * Sorts @queue using @func.
679
 *
680
 * The sort function @func is passed two elements of the @queue.
681
 * It should return 0 if they are equal, a negative value if the
682
 * first element should be higher in the @queue or a positive value
683
 * if the first element should be lower in the @queue than the second
684
 * element.
685
 *
686
 * This function will lock @queue before it sorts the queue and unlock
687
 * it when it is finished.
688
 *
689
 * If you were sorting a list of priority numbers to make sure the
690
 * lowest priority would be at the top of the queue, you could use:
691
 * |[<!-- language="C" -->
692
 *  gint32 id1;
693
 *  gint32 id2;
694
 *
695
 *  id1 = GPOINTER_TO_INT (element1);
696
 *  id2 = GPOINTER_TO_INT (element2);
697
 *
698
 *  return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
699
 * ]|
700
 *
701
 * Since: 2.10
702
 */
703
void
704
g_async_queue_sort (GAsyncQueue      *queue,
705
                    GCompareDataFunc  func,
706
                    gpointer          user_data)
707
0
{
708
0
  g_return_if_fail (queue != NULL);
709
0
  g_return_if_fail (func != NULL);
710
711
0
  g_mutex_lock (&queue->mutex);
712
0
  g_async_queue_sort_unlocked (queue, func, user_data);
713
0
  g_mutex_unlock (&queue->mutex);
714
0
}
715
716
/**
717
 * g_async_queue_sort_unlocked:
718
 * @queue: a #GAsyncQueue
719
 * @func: (scope call): the #GCompareDataFunc is used to sort @queue
720
 * @user_data: user data passed to @func
721
 *
722
 * Sorts @queue using @func.
723
 *
724
 * The sort function @func is passed two elements of the @queue.
725
 * It should return 0 if they are equal, a negative value if the
726
 * first element should be higher in the @queue or a positive value
727
 * if the first element should be lower in the @queue than the second
728
 * element.
729
 *
730
 * This function must be called while holding the @queue's lock.
731
 *
732
 * Since: 2.10
733
 */
734
void
735
g_async_queue_sort_unlocked (GAsyncQueue      *queue,
736
                             GCompareDataFunc  func,
737
                             gpointer          user_data)
738
0
{
739
0
  SortData sd;
740
741
0
  g_return_if_fail (queue != NULL);
742
0
  g_return_if_fail (func != NULL);
743
744
0
  sd.func = func;
745
0
  sd.user_data = user_data;
746
747
0
  g_queue_sort (&queue->queue,
748
0
                (GCompareDataFunc)g_async_queue_invert_compare,
749
0
                &sd);
750
0
}
751
752
/**
753
 * g_async_queue_remove:
754
 * @queue: a #GAsyncQueue
755
 * @item: (not nullable): the data to remove from the @queue
756
 *
757
 * Remove an item from the queue.
758
 *
759
 * Returns: %TRUE if the item was removed
760
 *
761
 * Since: 2.46
762
 */
763
gboolean
764
g_async_queue_remove (GAsyncQueue *queue,
765
                      gpointer     item)
766
15.3k
{
767
15.3k
  gboolean ret;
768
769
15.3k
  g_return_val_if_fail (queue != NULL, FALSE);
770
15.3k
  g_return_val_if_fail (item != NULL, FALSE);
771
772
15.3k
  g_mutex_lock (&queue->mutex);
773
15.3k
  ret = g_async_queue_remove_unlocked (queue, item);
774
15.3k
  g_mutex_unlock (&queue->mutex);
775
776
15.3k
  return ret;
777
15.3k
}
778
779
/**
780
 * g_async_queue_remove_unlocked:
781
 * @queue: a #GAsyncQueue
782
 * @item: the data to remove from the @queue
783
 *
784
 * Remove an item from the queue.
785
 *
786
 * This function must be called while holding the @queue's lock.
787
 *
788
 * Returns: %TRUE if the item was removed
789
 *
790
 * Since: 2.46
791
 */
792
gboolean
793
g_async_queue_remove_unlocked (GAsyncQueue *queue,
794
                               gpointer     item)
795
15.3k
{
796
15.3k
  g_return_val_if_fail (queue != NULL, FALSE);
797
15.3k
  g_return_val_if_fail (item != NULL, FALSE);
798
799
15.3k
  return g_queue_remove (&queue->queue, item);
800
15.3k
}
801
802
/**
803
 * g_async_queue_push_front:
804
 * @queue: a #GAsyncQueue
805
 * @item: (not nullable): data to push into the @queue
806
 *
807
 * Pushes the @item into the @queue. @item must not be %NULL.
808
 * In contrast to g_async_queue_push(), this function
809
 * pushes the new item ahead of the items already in the queue,
810
 * so that it will be the next one to be popped off the queue.
811
 *
812
 * Since: 2.46
813
 */
814
void
815
g_async_queue_push_front (GAsyncQueue *queue,
816
                          gpointer     item)
817
0
{
818
0
  g_return_if_fail (queue != NULL);
819
0
  g_return_if_fail (item != NULL);
820
821
0
  g_mutex_lock (&queue->mutex);
822
0
  g_async_queue_push_front_unlocked (queue, item);
823
0
  g_mutex_unlock (&queue->mutex);
824
0
}
825
826
/**
827
 * g_async_queue_push_front_unlocked:
828
 * @queue: a #GAsyncQueue
829
 * @item: (not nullable): data to push into the @queue
830
 *
831
 * Pushes the @item into the @queue. @item must not be %NULL.
832
 * In contrast to g_async_queue_push_unlocked(), this function
833
 * pushes the new item ahead of the items already in the queue,
834
 * so that it will be the next one to be popped off the queue.
835
 *
836
 * This function must be called while holding the @queue's lock.
837
 *
838
 * Since: 2.46
839
 */
840
void
841
g_async_queue_push_front_unlocked (GAsyncQueue *queue,
842
                                   gpointer     item)
843
0
{
844
0
  g_return_if_fail (queue != NULL);
845
0
  g_return_if_fail (item != NULL);
846
847
0
  g_queue_push_tail (&queue->queue, item);
848
0
  if (queue->waiting_threads > 0)
849
0
    g_cond_signal (&queue->cond);
850
0
}
851
852
/*
853
 * Private API
854
 */
855
856
GMutex *
857
_g_async_queue_get_mutex (GAsyncQueue *queue)
858
0
{
859
0
  g_return_val_if_fail (queue, NULL);
860
861
0
  return &queue->mutex;
862
0
}