1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GAsyncQueue: asynchronous queue implementation, based on GQueue.
5 * Copyright (C) 2000 Sebastian Wilhelmi; University of Karlsruhe
7 * SPDX-License-Identifier: LGPL-2.1-or-later
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.
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.
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/>.
29 #include "gasyncqueue.h"
30 #include "gasyncqueueprivate.h"
35 #include "gtestutils.h"
38 #include "deprecated/gthread.h"
42 * SECTION:async_queues
43 * @title: Asynchronous Queues
44 * @short_description: asynchronous communication between threads
45 * @see_also: #GThreadPool
47 * Often you need to communicate between different threads. In general
48 * it's safer not to do this by shared memory, but by explicit message
49 * passing. These messages only make sense asynchronously for
50 * multi-threaded applications though, as a synchronous operation could
51 * as well be done in the same thread.
53 * Asynchronous queues are an exception from most other GLib data
54 * structures, as they can be used simultaneously from multiple threads
55 * without explicit locking and they bring their own builtin reference
56 * counting. This is because the nature of an asynchronous queue is that
57 * it will always be used by at least 2 concurrent threads.
59 * For using an asynchronous queue you first have to create one with
60 * g_async_queue_new(). #GAsyncQueue structs are reference counted,
61 * use g_async_queue_ref() and g_async_queue_unref() to manage your
64 * A thread which wants to send a message to that queue simply calls
65 * g_async_queue_push() to push the message to the queue.
67 * A thread which is expecting messages from an asynchronous queue
68 * simply calls g_async_queue_pop() for that queue. If no message is
69 * available in the queue at that point, the thread is now put to sleep
70 * until a message arrives. The message will be removed from the queue
71 * and returned. The functions g_async_queue_try_pop() and
72 * g_async_queue_timeout_pop() can be used to only check for the presence
73 * of messages or to only wait a certain time for messages respectively.
75 * For almost every function there exist two variants, one that locks
76 * the queue and one that doesn't. That way you can hold the queue lock
77 * (acquire it with g_async_queue_lock() and release it with
78 * g_async_queue_unlock()) over multiple queue accessing instructions.
79 * This can be necessary to ensure the integrity of the queue, but should
80 * only be used when really necessary, as it can make your life harder
81 * if used unwisely. Normally you should only use the locking function
82 * variants (those without the _unlocked suffix).
84 * In many cases, it may be more convenient to use #GThreadPool when
85 * you need to distribute work to a set of worker threads instead of
86 * using #GAsyncQueue manually. #GThreadPool uses a GAsyncQueue
93 * An opaque data structure which represents an asynchronous queue.
95 * It should only be accessed through the `g_async_queue_*` functions.
102 GDestroyNotify item_free_func;
103 guint waiting_threads;
109 GCompareDataFunc func;
116 * Creates a new asynchronous queue.
118 * Returns: a new #GAsyncQueue. Free with g_async_queue_unref()
121 g_async_queue_new (void)
123 return g_async_queue_new_full (NULL);
127 * g_async_queue_new_full:
128 * @item_free_func: (nullable): function to free queue elements
130 * Creates a new asynchronous queue and sets up a destroy notify
131 * function that is used to free any remaining queue items when
132 * the queue is destroyed after the final unref.
134 * Returns: a new #GAsyncQueue. Free with g_async_queue_unref()
139 g_async_queue_new_full (GDestroyNotify item_free_func)
143 queue = g_new (GAsyncQueue, 1);
144 g_mutex_init (&queue->mutex);
145 g_cond_init (&queue->cond);
146 g_queue_init (&queue->queue);
147 queue->waiting_threads = 0;
148 queue->ref_count = 1;
149 queue->item_free_func = item_free_func;
156 * @queue: a #GAsyncQueue
158 * Increases the reference count of the asynchronous @queue by 1.
159 * You do not need to hold the lock to call this function.
161 * Returns: the @queue that was passed in (since 2.6)
164 g_async_queue_ref (GAsyncQueue *queue)
166 g_return_val_if_fail (queue, NULL);
168 g_atomic_int_inc (&queue->ref_count);
174 * g_async_queue_ref_unlocked:
175 * @queue: a #GAsyncQueue
177 * Increases the reference count of the asynchronous @queue by 1.
179 * Deprecated: 2.8: Reference counting is done atomically.
180 * so g_async_queue_ref() can be used regardless of the @queue's
184 g_async_queue_ref_unlocked (GAsyncQueue *queue)
186 g_return_if_fail (queue);
188 g_atomic_int_inc (&queue->ref_count);
192 * g_async_queue_unref_and_unlock:
193 * @queue: a #GAsyncQueue
195 * Decreases the reference count of the asynchronous @queue by 1
196 * and releases the lock. This function must be called while holding
197 * the @queue's lock. If the reference count went to 0, the @queue
198 * will be destroyed and the memory allocated will be freed.
200 * Deprecated: 2.8: Reference counting is done atomically.
201 * so g_async_queue_unref() can be used regardless of the @queue's
205 g_async_queue_unref_and_unlock (GAsyncQueue *queue)
207 g_return_if_fail (queue);
209 g_mutex_unlock (&queue->mutex);
210 g_async_queue_unref (queue);
214 * g_async_queue_unref:
215 * @queue: a #GAsyncQueue.
217 * Decreases the reference count of the asynchronous @queue by 1.
219 * If the reference count went to 0, the @queue will be destroyed
220 * and the memory allocated will be freed. So you are not allowed
221 * to use the @queue afterwards, as it might have disappeared.
222 * You do not need to hold the lock to call this function.
225 g_async_queue_unref (GAsyncQueue *queue)
227 g_return_if_fail (queue);
229 if (g_atomic_int_dec_and_test (&queue->ref_count))
231 g_return_if_fail (queue->waiting_threads == 0);
232 g_mutex_clear (&queue->mutex);
233 g_cond_clear (&queue->cond);
234 if (queue->item_free_func)
235 g_queue_foreach (&queue->queue, (GFunc) queue->item_free_func, NULL);
236 g_queue_clear (&queue->queue);
242 * g_async_queue_lock:
243 * @queue: a #GAsyncQueue
245 * Acquires the @queue's lock. If another thread is already
246 * holding the lock, this call will block until the lock
249 * Call g_async_queue_unlock() to drop the lock again.
251 * While holding the lock, you can only call the
252 * g_async_queue_*_unlocked() functions on @queue. Otherwise,
253 * deadlock may occur.
256 g_async_queue_lock (GAsyncQueue *queue)
258 g_return_if_fail (queue);
260 g_mutex_lock (&queue->mutex);
264 * g_async_queue_unlock:
265 * @queue: a #GAsyncQueue
267 * Releases the queue's lock.
269 * Calling this function when you have not acquired
270 * the with g_async_queue_lock() leads to undefined
274 g_async_queue_unlock (GAsyncQueue *queue)
276 g_return_if_fail (queue);
278 g_mutex_unlock (&queue->mutex);
282 * g_async_queue_push:
283 * @queue: a #GAsyncQueue
284 * @data: (not nullable): data to push onto the @queue
286 * Pushes the @data into the @queue.
288 * The @data parameter must not be %NULL.
291 g_async_queue_push (GAsyncQueue *queue,
294 g_return_if_fail (queue);
295 g_return_if_fail (data);
297 g_mutex_lock (&queue->mutex);
298 g_async_queue_push_unlocked (queue, data);
299 g_mutex_unlock (&queue->mutex);
303 * g_async_queue_push_unlocked:
304 * @queue: a #GAsyncQueue
305 * @data: (not nullable): data to push onto the @queue
307 * Pushes the @data into the @queue.
309 * The @data parameter must not be %NULL.
311 * This function must be called while holding the @queue's lock.
314 g_async_queue_push_unlocked (GAsyncQueue *queue,
317 g_return_if_fail (queue);
318 g_return_if_fail (data);
320 g_queue_push_head (&queue->queue, data);
321 if (queue->waiting_threads > 0)
322 g_cond_signal (&queue->cond);
326 * g_async_queue_push_sorted:
327 * @queue: a #GAsyncQueue
328 * @data: (not nullable): the @data to push into the @queue
329 * @func: the #GCompareDataFunc is used to sort @queue
330 * @user_data: user data passed to @func.
332 * Inserts @data into @queue using @func to determine the new
335 * This function requires that the @queue is sorted before pushing on
336 * new elements, see g_async_queue_sort().
338 * This function will lock @queue before it sorts the queue and unlock
339 * it when it is finished.
341 * For an example of @func see g_async_queue_sort().
346 g_async_queue_push_sorted (GAsyncQueue *queue,
348 GCompareDataFunc func,
351 g_return_if_fail (queue != NULL);
353 g_mutex_lock (&queue->mutex);
354 g_async_queue_push_sorted_unlocked (queue, data, func, user_data);
355 g_mutex_unlock (&queue->mutex);
359 g_async_queue_invert_compare (gpointer v1,
363 return -sd->func (v1, v2, sd->user_data);
367 * g_async_queue_push_sorted_unlocked:
368 * @queue: a #GAsyncQueue
369 * @data: the data to push into the @queue
370 * @func: the #GCompareDataFunc is used to sort @queue
371 * @user_data: user data passed to @func.
373 * Inserts @data into @queue using @func to determine the new
376 * The sort function @func is passed two elements of the @queue.
377 * It should return 0 if they are equal, a negative value if the
378 * first element should be higher in the @queue or a positive value
379 * if the first element should be lower in the @queue than the second
382 * This function requires that the @queue is sorted before pushing on
383 * new elements, see g_async_queue_sort().
385 * This function must be called while holding the @queue's lock.
387 * For an example of @func see g_async_queue_sort().
392 g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
394 GCompareDataFunc func,
399 g_return_if_fail (queue != NULL);
402 sd.user_data = user_data;
404 g_queue_insert_sorted (&queue->queue,
406 (GCompareDataFunc)g_async_queue_invert_compare,
408 if (queue->waiting_threads > 0)
409 g_cond_signal (&queue->cond);
413 g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
419 if (!g_queue_peek_tail_link (&queue->queue) && wait)
421 queue->waiting_threads++;
422 while (!g_queue_peek_tail_link (&queue->queue))
425 g_cond_wait (&queue->cond, &queue->mutex);
428 if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time))
432 queue->waiting_threads--;
435 retval = g_queue_pop_tail (&queue->queue);
437 g_assert (retval || !wait || end_time > 0);
444 * @queue: a #GAsyncQueue
446 * Pops data from the @queue. If @queue is empty, this function
447 * blocks until data becomes available.
449 * Returns: data from the queue
452 g_async_queue_pop (GAsyncQueue *queue)
456 g_return_val_if_fail (queue, NULL);
458 g_mutex_lock (&queue->mutex);
459 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
460 g_mutex_unlock (&queue->mutex);
466 * g_async_queue_pop_unlocked:
467 * @queue: a #GAsyncQueue
469 * Pops data from the @queue. If @queue is empty, this function
470 * blocks until data becomes available.
472 * This function must be called while holding the @queue's lock.
474 * Returns: data from the queue.
477 g_async_queue_pop_unlocked (GAsyncQueue *queue)
479 g_return_val_if_fail (queue, NULL);
481 return g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
485 * g_async_queue_try_pop:
486 * @queue: a #GAsyncQueue
488 * Tries to pop data from the @queue. If no data is available,
491 * Returns: (nullable): data from the queue or %NULL, when no data is
492 * available immediately.
495 g_async_queue_try_pop (GAsyncQueue *queue)
499 g_return_val_if_fail (queue, NULL);
501 g_mutex_lock (&queue->mutex);
502 retval = g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
503 g_mutex_unlock (&queue->mutex);
509 * g_async_queue_try_pop_unlocked:
510 * @queue: a #GAsyncQueue
512 * Tries to pop data from the @queue. If no data is available,
515 * This function must be called while holding the @queue's lock.
517 * Returns: (nullable): data from the queue or %NULL, when no data is
518 * available immediately.
521 g_async_queue_try_pop_unlocked (GAsyncQueue *queue)
523 g_return_val_if_fail (queue, NULL);
525 return g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
529 * g_async_queue_timeout_pop:
530 * @queue: a #GAsyncQueue
531 * @timeout: the number of microseconds to wait
533 * Pops data from the @queue. If the queue is empty, blocks for
534 * @timeout microseconds, or until data becomes available.
536 * If no data is received before the timeout, %NULL is returned.
538 * Returns: (nullable): data from the queue or %NULL, when no data is
539 * received before the timeout.
542 g_async_queue_timeout_pop (GAsyncQueue *queue,
545 gint64 end_time = g_get_monotonic_time () + timeout;
548 g_return_val_if_fail (queue != NULL, NULL);
550 g_mutex_lock (&queue->mutex);
551 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
552 g_mutex_unlock (&queue->mutex);
558 * g_async_queue_timeout_pop_unlocked:
559 * @queue: a #GAsyncQueue
560 * @timeout: the number of microseconds to wait
562 * Pops data from the @queue. If the queue is empty, blocks for
563 * @timeout microseconds, or until data becomes available.
565 * If no data is received before the timeout, %NULL is returned.
567 * This function must be called while holding the @queue's lock.
569 * Returns: (nullable): data from the queue or %NULL, when no data is
570 * received before the timeout.
573 g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
576 gint64 end_time = g_get_monotonic_time () + timeout;
578 g_return_val_if_fail (queue != NULL, NULL);
580 return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
584 * g_async_queue_timed_pop:
585 * @queue: a #GAsyncQueue
586 * @end_time: a #GTimeVal, determining the final time
588 * Pops data from the @queue. If the queue is empty, blocks until
589 * @end_time or until data becomes available.
591 * If no data is received before @end_time, %NULL is returned.
593 * To easily calculate @end_time, a combination of g_get_real_time()
594 * and g_time_val_add() can be used.
596 * Returns: (nullable): data from the queue or %NULL, when no data is
597 * received before @end_time.
599 * Deprecated: use g_async_queue_timeout_pop().
601 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
603 g_async_queue_timed_pop (GAsyncQueue *queue,
609 g_return_val_if_fail (queue, NULL);
611 if (end_time != NULL)
613 m_end_time = g_get_monotonic_time () +
614 ((gint64) end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - g_get_real_time ());
619 g_mutex_lock (&queue->mutex);
620 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
621 g_mutex_unlock (&queue->mutex);
625 G_GNUC_END_IGNORE_DEPRECATIONS
628 * g_async_queue_timed_pop_unlocked:
629 * @queue: a #GAsyncQueue
630 * @end_time: a #GTimeVal, determining the final time
632 * Pops data from the @queue. If the queue is empty, blocks until
633 * @end_time or until data becomes available.
635 * If no data is received before @end_time, %NULL is returned.
637 * To easily calculate @end_time, a combination of g_get_real_time()
638 * and g_time_val_add() can be used.
640 * This function must be called while holding the @queue's lock.
642 * Returns: (nullable): data from the queue or %NULL, when no data is
643 * received before @end_time.
645 * Deprecated: use g_async_queue_timeout_pop_unlocked().
647 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
649 g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
654 g_return_val_if_fail (queue, NULL);
656 if (end_time != NULL)
658 m_end_time = g_get_monotonic_time () +
659 ((gint64) end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - g_get_real_time ());
664 return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
666 G_GNUC_END_IGNORE_DEPRECATIONS
669 * g_async_queue_length:
670 * @queue: a #GAsyncQueue.
672 * Returns the length of the queue.
674 * Actually this function returns the number of data items in
675 * the queue minus the number of waiting threads, so a negative
676 * value means waiting threads, and a positive value means available
677 * entries in the @queue. A return value of 0 could mean n entries
678 * in the queue and n threads waiting. This can happen due to locking
679 * of the queue or due to scheduling.
681 * Returns: the length of the @queue
684 g_async_queue_length (GAsyncQueue *queue)
688 g_return_val_if_fail (queue, 0);
690 g_mutex_lock (&queue->mutex);
691 retval = queue->queue.length - queue->waiting_threads;
692 g_mutex_unlock (&queue->mutex);
698 * g_async_queue_length_unlocked:
699 * @queue: a #GAsyncQueue
701 * Returns the length of the queue.
703 * Actually this function returns the number of data items in
704 * the queue minus the number of waiting threads, so a negative
705 * value means waiting threads, and a positive value means available
706 * entries in the @queue. A return value of 0 could mean n entries
707 * in the queue and n threads waiting. This can happen due to locking
708 * of the queue or due to scheduling.
710 * This function must be called while holding the @queue's lock.
712 * Returns: the length of the @queue.
715 g_async_queue_length_unlocked (GAsyncQueue *queue)
717 g_return_val_if_fail (queue, 0);
719 return queue->queue.length - queue->waiting_threads;
723 * g_async_queue_sort:
724 * @queue: a #GAsyncQueue
725 * @func: the #GCompareDataFunc is used to sort @queue
726 * @user_data: user data passed to @func
728 * Sorts @queue using @func.
730 * The sort function @func is passed two elements of the @queue.
731 * It should return 0 if they are equal, a negative value if the
732 * first element should be higher in the @queue or a positive value
733 * if the first element should be lower in the @queue than the second
736 * This function will lock @queue before it sorts the queue and unlock
737 * it when it is finished.
739 * If you were sorting a list of priority numbers to make sure the
740 * lowest priority would be at the top of the queue, you could use:
741 * |[<!-- language="C" -->
745 * id1 = GPOINTER_TO_INT (element1);
746 * id2 = GPOINTER_TO_INT (element2);
748 * return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
754 g_async_queue_sort (GAsyncQueue *queue,
755 GCompareDataFunc func,
758 g_return_if_fail (queue != NULL);
759 g_return_if_fail (func != NULL);
761 g_mutex_lock (&queue->mutex);
762 g_async_queue_sort_unlocked (queue, func, user_data);
763 g_mutex_unlock (&queue->mutex);
767 * g_async_queue_sort_unlocked:
768 * @queue: a #GAsyncQueue
769 * @func: the #GCompareDataFunc is used to sort @queue
770 * @user_data: user data passed to @func
772 * Sorts @queue using @func.
774 * The sort function @func is passed two elements of the @queue.
775 * It should return 0 if they are equal, a negative value if the
776 * first element should be higher in the @queue or a positive value
777 * if the first element should be lower in the @queue than the second
780 * This function must be called while holding the @queue's lock.
785 g_async_queue_sort_unlocked (GAsyncQueue *queue,
786 GCompareDataFunc func,
791 g_return_if_fail (queue != NULL);
792 g_return_if_fail (func != NULL);
795 sd.user_data = user_data;
797 g_queue_sort (&queue->queue,
798 (GCompareDataFunc)g_async_queue_invert_compare,
803 * g_async_queue_remove:
804 * @queue: a #GAsyncQueue
805 * @item: (not nullable): the data to remove from the @queue
807 * Remove an item from the queue.
809 * Returns: %TRUE if the item was removed
814 g_async_queue_remove (GAsyncQueue *queue,
819 g_return_val_if_fail (queue != NULL, FALSE);
820 g_return_val_if_fail (item != NULL, FALSE);
822 g_mutex_lock (&queue->mutex);
823 ret = g_async_queue_remove_unlocked (queue, item);
824 g_mutex_unlock (&queue->mutex);
830 * g_async_queue_remove_unlocked:
831 * @queue: a #GAsyncQueue
832 * @item: the data to remove from the @queue
834 * Remove an item from the queue.
836 * This function must be called while holding the @queue's lock.
838 * Returns: %TRUE if the item was removed
843 g_async_queue_remove_unlocked (GAsyncQueue *queue,
846 g_return_val_if_fail (queue != NULL, FALSE);
847 g_return_val_if_fail (item != NULL, FALSE);
849 return g_queue_remove (&queue->queue, item);
853 * g_async_queue_push_front:
854 * @queue: a #GAsyncQueue
855 * @item: (not nullable): data to push into the @queue
857 * Pushes the @item into the @queue. @item must not be %NULL.
858 * In contrast to g_async_queue_push(), this function
859 * pushes the new item ahead of the items already in the queue,
860 * so that it will be the next one to be popped off the queue.
865 g_async_queue_push_front (GAsyncQueue *queue,
868 g_return_if_fail (queue != NULL);
869 g_return_if_fail (item != NULL);
871 g_mutex_lock (&queue->mutex);
872 g_async_queue_push_front_unlocked (queue, item);
873 g_mutex_unlock (&queue->mutex);
877 * g_async_queue_push_front_unlocked:
878 * @queue: a #GAsyncQueue
879 * @item: (not nullable): data to push into the @queue
881 * Pushes the @item into the @queue. @item must not be %NULL.
882 * In contrast to g_async_queue_push_unlocked(), this function
883 * pushes the new item ahead of the items already in the queue,
884 * so that it will be the next one to be popped off the queue.
886 * This function must be called while holding the @queue's lock.
891 g_async_queue_push_front_unlocked (GAsyncQueue *queue,
894 g_return_if_fail (queue != NULL);
895 g_return_if_fail (item != NULL);
897 g_queue_push_tail (&queue->queue, item);
898 if (queue->waiting_threads > 0)
899 g_cond_signal (&queue->cond);
907 _g_async_queue_get_mutex (GAsyncQueue *queue)
909 g_return_val_if_fail (queue, NULL);
911 return &queue->mutex;