GSettings docs: clarify what is a good path
[glib.git] / glib / gasyncqueue.c
blob075266f5fee266f45ce7149499858f8baad22f9e
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 * 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 * MT safe
27 #include "config.h"
29 #include "gasyncqueue.h"
30 #include "gasyncqueueprivate.h"
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"
41 /**
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
62 * references.
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
87 * internally.
90 /**
91 * GAsyncQueue:
93 * The GAsyncQueue struct is an opaque data structure which represents
94 * an asynchronous queue. It should only be accessed through the
95 * <function>g_async_queue_*</function> functions.
97 struct _GAsyncQueue
99 GMutex mutex;
100 GCond cond;
101 GQueue queue;
102 GDestroyNotify item_free_func;
103 guint waiting_threads;
104 gint ref_count;
107 typedef struct
109 GCompareDataFunc func;
110 gpointer user_data;
111 } SortData;
114 * g_async_queue_new:
116 * Creates a new asynchronous queue.
118 * Return value: a new #GAsyncQueue. Free with g_async_queue_unref()
120 GAsyncQueue *
121 g_async_queue_new (void)
123 return g_async_queue_new_full (NULL);
127 * g_async_queue_new_full:
128 * @item_free_func: 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 * Return value: a new #GAsyncQueue. Free with g_async_queue_unref()
136 * Since: 2.16
138 GAsyncQueue *
139 g_async_queue_new_full (GDestroyNotify item_free_func)
141 GAsyncQueue *queue;
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;
151 return queue;
155 * g_async_queue_ref:
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)
163 GAsyncQueue *
164 g_async_queue_ref (GAsyncQueue *queue)
166 g_return_val_if_fail (queue, NULL);
168 g_atomic_int_inc (&queue->ref_count);
170 return queue;
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
181 * lock.
183 void
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
202 * lock.
204 void
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.
224 void
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);
237 g_free (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
247 * becomes available.
249 * Call g_async_queue_unlock() to drop the lock again.
251 * While holding the lock, you can only call the
252 * <function>g_async_queue_*_unlocked()</function> functions
253 * on @queue. Otherwise, deadlock may occur.
255 void
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
271 * behaviour.
273 void
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: @data to push into the @queue
286 * Pushes the @data into the @queue. @data must not be %NULL.
288 void
289 g_async_queue_push (GAsyncQueue *queue,
290 gpointer data)
292 g_return_if_fail (queue);
293 g_return_if_fail (data);
295 g_mutex_lock (&queue->mutex);
296 g_async_queue_push_unlocked (queue, data);
297 g_mutex_unlock (&queue->mutex);
301 * g_async_queue_push_unlocked:
302 * @queue: a #GAsyncQueue
303 * @data: @data to push into the @queue
305 * Pushes the @data into the @queue. @data must not be %NULL.
307 * This function must be called while holding the @queue's lock.
309 void
310 g_async_queue_push_unlocked (GAsyncQueue *queue,
311 gpointer data)
313 g_return_if_fail (queue);
314 g_return_if_fail (data);
316 g_queue_push_head (&queue->queue, data);
317 if (queue->waiting_threads > 0)
318 g_cond_signal (&queue->cond);
322 * g_async_queue_push_sorted:
323 * @queue: a #GAsyncQueue
324 * @data: the @data to push into the @queue
325 * @func: the #GCompareDataFunc is used to sort @queue
326 * @user_data: user data passed to @func.
328 * Inserts @data into @queue using @func to determine the new
329 * position.
331 * This function requires that the @queue is sorted before pushing on
332 * new elements, see g_async_queue_sort().
334 * This function will lock @queue before it sorts the queue and unlock
335 * it when it is finished.
337 * For an example of @func see g_async_queue_sort().
339 * Since: 2.10
341 void
342 g_async_queue_push_sorted (GAsyncQueue *queue,
343 gpointer data,
344 GCompareDataFunc func,
345 gpointer user_data)
347 g_return_if_fail (queue != NULL);
349 g_mutex_lock (&queue->mutex);
350 g_async_queue_push_sorted_unlocked (queue, data, func, user_data);
351 g_mutex_unlock (&queue->mutex);
354 static gint
355 g_async_queue_invert_compare (gpointer v1,
356 gpointer v2,
357 SortData *sd)
359 return -sd->func (v1, v2, sd->user_data);
363 * g_async_queue_push_sorted_unlocked:
364 * @queue: a #GAsyncQueue
365 * @data: the @data to push into the @queue
366 * @func: the #GCompareDataFunc is used to sort @queue
367 * @user_data: user data passed to @func.
369 * Inserts @data into @queue using @func to determine the new
370 * position.
372 * The sort function @func is passed two elements of the @queue.
373 * It should return 0 if they are equal, a negative value if the
374 * first element should be higher in the @queue or a positive value
375 * if the first element should be lower in the @queue than the second
376 * element.
378 * This function requires that the @queue is sorted before pushing on
379 * new elements, see g_async_queue_sort().
381 * This function must be called while holding the @queue's lock.
383 * For an example of @func see g_async_queue_sort().
385 * Since: 2.10
387 void
388 g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
389 gpointer data,
390 GCompareDataFunc func,
391 gpointer user_data)
393 SortData sd;
395 g_return_if_fail (queue != NULL);
397 sd.func = func;
398 sd.user_data = user_data;
400 g_queue_insert_sorted (&queue->queue,
401 data,
402 (GCompareDataFunc)g_async_queue_invert_compare,
403 &sd);
404 if (queue->waiting_threads > 0)
405 g_cond_signal (&queue->cond);
408 static gpointer
409 g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
410 gboolean wait,
411 gint64 end_time)
413 gpointer retval;
415 if (!g_queue_peek_tail_link (&queue->queue) && wait)
417 queue->waiting_threads++;
418 while (!g_queue_peek_tail_link (&queue->queue))
420 if (end_time == -1)
421 g_cond_wait (&queue->cond, &queue->mutex);
422 else
424 if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time))
425 break;
428 queue->waiting_threads--;
431 retval = g_queue_pop_tail (&queue->queue);
433 g_assert (retval || !wait || end_time > 0);
435 return retval;
439 * g_async_queue_pop:
440 * @queue: a #GAsyncQueue
442 * Pops data from the @queue. If @queue is empty, this function
443 * blocks until data becomes available.
445 * Return value: data from the queue
447 gpointer
448 g_async_queue_pop (GAsyncQueue *queue)
450 gpointer retval;
452 g_return_val_if_fail (queue, NULL);
454 g_mutex_lock (&queue->mutex);
455 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
456 g_mutex_unlock (&queue->mutex);
458 return retval;
462 * g_async_queue_pop_unlocked:
463 * @queue: a #GAsyncQueue
465 * Pops data from the @queue. If @queue is empty, this function
466 * blocks until data becomes available.
468 * This function must be called while holding the @queue's lock.
470 * Return value: data from the queue.
472 gpointer
473 g_async_queue_pop_unlocked (GAsyncQueue *queue)
475 g_return_val_if_fail (queue, NULL);
477 return g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
481 * g_async_queue_try_pop:
482 * @queue: a #GAsyncQueue
484 * Tries to pop data from the @queue. If no data is available,
485 * %NULL is returned.
487 * Return value: data from the queue or %NULL, when no data is
488 * available immediately.
490 gpointer
491 g_async_queue_try_pop (GAsyncQueue *queue)
493 gpointer retval;
495 g_return_val_if_fail (queue, NULL);
497 g_mutex_lock (&queue->mutex);
498 retval = g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
499 g_mutex_unlock (&queue->mutex);
501 return retval;
505 * g_async_queue_try_pop_unlocked:
506 * @queue: a #GAsyncQueue
508 * Tries to pop data from the @queue. If no data is available,
509 * %NULL is returned.
511 * This function must be called while holding the @queue's lock.
513 * Return value: data from the queue or %NULL, when no data is
514 * available immediately.
516 gpointer
517 g_async_queue_try_pop_unlocked (GAsyncQueue *queue)
519 g_return_val_if_fail (queue, NULL);
521 return g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
525 * g_async_queue_timeout_pop:
526 * @queue: a #GAsyncQueue
527 * @timeout: the number of microseconds to wait
529 * Pops data from the @queue. If the queue is empty, blocks for
530 * @timeout microseconds, or until data becomes available.
532 * If no data is received before the timeout, %NULL is returned.
534 * Return value: data from the queue or %NULL, when no data is
535 * received before the timeout.
537 gpointer
538 g_async_queue_timeout_pop (GAsyncQueue *queue,
539 guint64 timeout)
541 gint64 end_time = g_get_monotonic_time () + timeout;
542 gpointer retval;
544 g_mutex_lock (&queue->mutex);
545 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
546 g_mutex_unlock (&queue->mutex);
548 return retval;
552 * g_async_queue_timeout_pop_unlocked:
553 * @queue: a #GAsyncQueue
554 * @timeout: the number of microseconds to wait
556 * Pops data from the @queue. If the queue is empty, blocks for
557 * @timeout microseconds, or until data becomes available.
559 * If no data is received before the timeout, %NULL is returned.
561 * This function must be called while holding the @queue's lock.
563 * Return value: data from the queue or %NULL, when no data is
564 * received before the timeout.
566 gpointer
567 g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
568 guint64 timeout)
570 gint64 end_time = g_get_monotonic_time () + timeout;
572 return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
576 * g_async_queue_timed_pop:
577 * @queue: a #GAsyncQueue
578 * @end_time: a #GTimeVal, determining the final time
580 * Pops data from the @queue. If the queue is empty, blocks until
581 * @end_time or until data becomes available.
583 * If no data is received before @end_time, %NULL is returned.
585 * To easily calculate @end_time, a combination of g_get_current_time()
586 * and g_time_val_add() can be used.
588 * Return value: data from the queue or %NULL, when no data is
589 * received before @end_time.
591 * Deprecated: use g_async_queue_timeout_pop().
593 gpointer
594 g_async_queue_timed_pop (GAsyncQueue *queue,
595 GTimeVal *end_time)
597 gint64 m_end_time;
598 gpointer retval;
600 g_return_val_if_fail (queue, NULL);
602 if (end_time != NULL)
604 m_end_time = g_get_monotonic_time () +
605 ((gint64)end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec -
606 g_get_real_time ());
608 else
609 m_end_time = -1;
611 g_mutex_lock (&queue->mutex);
612 retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
613 g_mutex_unlock (&queue->mutex);
615 return retval;
619 * g_async_queue_timed_pop_unlocked:
620 * @queue: a #GAsyncQueue
621 * @end_time: a #GTimeVal, determining the final time
623 * Pops data from the @queue. If the queue is empty, blocks until
624 * @end_time or until data becomes available.
626 * If no data is received before @end_time, %NULL is returned.
628 * To easily calculate @end_time, a combination of g_get_current_time()
629 * and g_time_val_add() can be used.
631 * This function must be called while holding the @queue's lock.
633 * Return value: data from the queue or %NULL, when no data is
634 * received before @end_time.
636 * Deprecated: use g_async_queue_timeout_pop_unlocked().
638 gpointer
639 g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
640 GTimeVal *end_time)
642 gint64 m_end_time;
644 g_return_val_if_fail (queue, NULL);
646 if (end_time != NULL)
648 m_end_time = g_get_monotonic_time () +
649 (end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec -
650 g_get_real_time ());
652 else
653 m_end_time = -1;
655 return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
659 * g_async_queue_length:
660 * @queue: a #GAsyncQueue.
662 * Returns the length of the queue.
664 * Actually this function returns the number of data items in
665 * the queue minus the number of waiting threads, so a negative
666 * value means waiting threads, and a positive value means available
667 * entries in the @queue. A return value of 0 could mean n entries
668 * in the queue and n threads waiting. This can happen due to locking
669 * of the queue or due to scheduling.
671 * Return value: the length of the @queue
673 gint
674 g_async_queue_length (GAsyncQueue *queue)
676 gint retval;
678 g_return_val_if_fail (queue, 0);
680 g_mutex_lock (&queue->mutex);
681 retval = queue->queue.length - queue->waiting_threads;
682 g_mutex_unlock (&queue->mutex);
684 return retval;
688 * g_async_queue_length_unlocked:
689 * @queue: a #GAsyncQueue
691 * Returns the length of the queue.
693 * Actually this function returns the number of data items in
694 * the queue minus the number of waiting threads, so a negative
695 * value means waiting threads, and a positive value means available
696 * entries in the @queue. A return value of 0 could mean n entries
697 * in the queue and n threads waiting. This can happen due to locking
698 * of the queue or due to scheduling.
700 * This function must be called while holding the @queue's lock.
702 * Return value: the length of the @queue.
704 gint
705 g_async_queue_length_unlocked (GAsyncQueue *queue)
707 g_return_val_if_fail (queue, 0);
709 return queue->queue.length - queue->waiting_threads;
713 * g_async_queue_sort:
714 * @queue: a #GAsyncQueue
715 * @func: the #GCompareDataFunc is used to sort @queue
716 * @user_data: user data passed to @func
718 * Sorts @queue using @func.
720 * The sort function @func is passed two elements of the @queue.
721 * It should return 0 if they are equal, a negative value if the
722 * first element should be higher in the @queue or a positive value
723 * if the first element should be lower in the @queue than the second
724 * element.
726 * This function will lock @queue before it sorts the queue and unlock
727 * it when it is finished.
729 * If you were sorting a list of priority numbers to make sure the
730 * lowest priority would be at the top of the queue, you could use:
731 * |[
732 * gint32 id1;
733 * gint32 id2;
735 * id1 = GPOINTER_TO_INT (element1);
736 * id2 = GPOINTER_TO_INT (element2);
738 * return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
739 * ]|
741 * Since: 2.10
743 void
744 g_async_queue_sort (GAsyncQueue *queue,
745 GCompareDataFunc func,
746 gpointer user_data)
748 g_return_if_fail (queue != NULL);
749 g_return_if_fail (func != NULL);
751 g_mutex_lock (&queue->mutex);
752 g_async_queue_sort_unlocked (queue, func, user_data);
753 g_mutex_unlock (&queue->mutex);
757 * g_async_queue_sort_unlocked:
758 * @queue: a #GAsyncQueue
759 * @func: the #GCompareDataFunc is used to sort @queue
760 * @user_data: user data passed to @func
762 * Sorts @queue using @func.
764 * The sort function @func is passed two elements of the @queue.
765 * It should return 0 if they are equal, a negative value if the
766 * first element should be higher in the @queue or a positive value
767 * if the first element should be lower in the @queue than the second
768 * element.
770 * This function must be called while holding the @queue's lock.
772 * Since: 2.10
774 void
775 g_async_queue_sort_unlocked (GAsyncQueue *queue,
776 GCompareDataFunc func,
777 gpointer user_data)
779 SortData sd;
781 g_return_if_fail (queue != NULL);
782 g_return_if_fail (func != NULL);
784 sd.func = func;
785 sd.user_data = user_data;
787 g_queue_sort (&queue->queue,
788 (GCompareDataFunc)g_async_queue_invert_compare,
789 &sd);
793 * Private API
796 GMutex *
797 _g_async_queue_get_mutex (GAsyncQueue *queue)
799 g_return_val_if_fail (queue, NULL);
801 return &queue->mutex;