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.
37 guint waiting_threads
;
44 * Creates a new asynchronous queue with the initial reference count of 1.
46 * Return value: the new #GAsyncQueue.
51 GAsyncQueue
* retval
= g_new (GAsyncQueue
, 1);
52 retval
->mutex
= g_mutex_new ();
54 retval
->queue
= g_queue_new ();
55 retval
->waiting_threads
= 0;
56 retval
->ref_count
= 1;
62 * @queue: a #GAsyncQueue.
64 * Increases the reference count of the asynchronous @queue by 1. You
65 * do not need to hold the lock to call this function.
68 g_async_queue_ref (GAsyncQueue
*queue
)
70 g_return_if_fail (queue
);
71 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
73 g_atomic_int_inc (&queue
->ref_count
);
77 * g_async_queue_ref_unlocked:
78 * @queue: a #GAsyncQueue.
80 * Increases the reference count of the asynchronous @queue by 1.
83 g_async_queue_ref_unlocked (GAsyncQueue
*queue
)
85 g_return_if_fail (queue
);
86 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
88 g_atomic_int_inc (&queue
->ref_count
);
92 * g_async_queue_unref_and_unlock:
93 * @queue: a #GAsyncQueue.
95 * Decreases the reference count of the asynchronous @queue by 1 and
96 * releases the lock. This function must be called while holding the
97 * @queue's lock. If the reference count went to 0, the @queue will be
98 * destroyed and the memory allocated will be freed.
101 g_async_queue_unref_and_unlock (GAsyncQueue
*queue
)
103 g_return_if_fail (queue
);
104 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
106 g_mutex_unlock (queue
->mutex
);
107 g_async_queue_unref (queue
);
111 * g_async_queue_unref:
112 * @queue: a #GAsyncQueue.
114 * Decreases the reference count of the asynchronous @queue by 1. If
115 * the reference count went to 0, the @queue will be destroyed and the
116 * memory allocated will be freed. So you are not allowed to use the
117 * @queue afterwards, as it might have disappeared. You do not need to
118 * hold the lock to call this function.
121 g_async_queue_unref (GAsyncQueue
*queue
)
123 g_return_if_fail (queue
);
124 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
126 if (g_atomic_int_dec_and_test (&queue
->ref_count
))
128 g_return_if_fail (queue
->waiting_threads
== 0);
129 g_mutex_free (queue
->mutex
);
131 g_cond_free (queue
->cond
);
132 g_queue_free (queue
->queue
);
138 * g_async_queue_lock:
139 * @queue: a #GAsyncQueue.
141 * Acquires the @queue's lock. After that you can only call the
142 * <function>g_async_queue_*_unlocked()</function> function variants on that
143 * @queue. Otherwise it will deadlock.
146 g_async_queue_lock (GAsyncQueue
*queue
)
148 g_return_if_fail (queue
);
149 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
151 g_mutex_lock (queue
->mutex
);
155 * g_async_queue_unlock:
156 * @queue: a #GAsyncQueue.
158 * Releases the queue's lock.
161 g_async_queue_unlock (GAsyncQueue
*queue
)
163 g_return_if_fail (queue
);
164 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
166 g_mutex_unlock (queue
->mutex
);
170 * g_async_queue_push:
171 * @queue: a #GAsyncQueue.
172 * @data: @data to push into the @queue.
174 * Pushes the @data into the @queue. @data must not be %NULL.
177 g_async_queue_push (GAsyncQueue
* queue
, gpointer data
)
179 g_return_if_fail (queue
);
180 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
181 g_return_if_fail (data
);
183 g_mutex_lock (queue
->mutex
);
184 g_async_queue_push_unlocked (queue
, data
);
185 g_mutex_unlock (queue
->mutex
);
189 * g_async_queue_push_unlocked:
190 * @queue: a #GAsyncQueue.
191 * @data: @data to push into the @queue.
193 * Pushes the @data into the @queue. @data must not be %NULL. This
194 * function must be called while holding the @queue's lock.
197 g_async_queue_push_unlocked (GAsyncQueue
* queue
, gpointer data
)
199 g_return_if_fail (queue
);
200 g_return_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0);
201 g_return_if_fail (data
);
203 g_queue_push_head (queue
->queue
, data
);
204 if (queue
->waiting_threads
> 0)
205 g_cond_signal (queue
->cond
);
209 g_async_queue_pop_intern_unlocked (GAsyncQueue
* queue
, gboolean
try,
214 if (!g_queue_peek_tail (queue
->queue
))
220 queue
->cond
= g_cond_new ();
224 queue
->waiting_threads
++;
225 while (!g_queue_peek_tail (queue
->queue
))
226 g_cond_wait(queue
->cond
, queue
->mutex
);
227 queue
->waiting_threads
--;
231 queue
->waiting_threads
++;
232 while (!g_queue_peek_tail (queue
->queue
))
233 if (!g_cond_timed_wait (queue
->cond
, queue
->mutex
, end_time
))
235 queue
->waiting_threads
--;
236 if (!g_queue_peek_tail (queue
->queue
))
241 retval
= g_queue_pop_tail (queue
->queue
);
250 * @queue: a #GAsyncQueue.
252 * Pops data from the @queue. This function blocks until data become
255 * Return value: data from the queue.
258 g_async_queue_pop (GAsyncQueue
* queue
)
262 g_return_val_if_fail (queue
, NULL
);
263 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
265 g_mutex_lock (queue
->mutex
);
266 retval
= g_async_queue_pop_intern_unlocked (queue
, FALSE
, NULL
);
267 g_mutex_unlock (queue
->mutex
);
273 * g_async_queue_pop_unlocked:
274 * @queue: a #GAsyncQueue.
276 * Pops data from the @queue. This function blocks until data become
277 * available. This function must be called while holding the @queue's
280 * Return value: data from the queue.
283 g_async_queue_pop_unlocked (GAsyncQueue
* queue
)
285 g_return_val_if_fail (queue
, NULL
);
286 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
288 return g_async_queue_pop_intern_unlocked (queue
, FALSE
, NULL
);
292 * g_async_queue_try_pop:
293 * @queue: a #GAsyncQueue.
295 * Tries to pop data from the @queue. If no data is available, %NULL is
298 * Return value: data from the queue or %NULL, when no data is
299 * available immediately.
302 g_async_queue_try_pop (GAsyncQueue
* queue
)
306 g_return_val_if_fail (queue
, NULL
);
307 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
309 g_mutex_lock (queue
->mutex
);
310 retval
= g_async_queue_pop_intern_unlocked (queue
, TRUE
, NULL
);
311 g_mutex_unlock (queue
->mutex
);
317 * g_async_queue_try_pop_unlocked:
318 * @queue: a #GAsyncQueue.
320 * Tries to pop data from the @queue. If no data is available, %NULL is
321 * returned. This function must be called while holding the @queue's
324 * Return value: data from the queue or %NULL, when no data is
325 * available immediately.
328 g_async_queue_try_pop_unlocked (GAsyncQueue
* queue
)
330 g_return_val_if_fail (queue
, NULL
);
331 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
333 return g_async_queue_pop_intern_unlocked (queue
, TRUE
, NULL
);
337 * g_async_queue_timed_pop:
338 * @queue: a #GAsyncQueue.
339 * @end_time: a #GTimeVal, determining the final time.
341 * Pops data from the @queue. If no data is received before @end_time,
344 * To easily calculate @end_time a combination of g_get_current_time()
345 * and g_time_val_add() can be used.
347 * Return value: data from the queue or %NULL, when no data is
348 * received before @end_time.
351 g_async_queue_timed_pop (GAsyncQueue
* queue
, GTimeVal
*end_time
)
355 g_return_val_if_fail (queue
, NULL
);
356 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
358 g_mutex_lock (queue
->mutex
);
359 retval
= g_async_queue_pop_intern_unlocked (queue
, FALSE
, end_time
);
360 g_mutex_unlock (queue
->mutex
);
366 * g_async_queue_timed_pop_unlocked:
367 * @queue: a #GAsyncQueue.
368 * @end_time: a #GTimeVal, determining the final time.
370 * Pops data from the @queue. If no data is received before @end_time,
371 * %NULL is returned. This function must be called while holding the
374 * To easily calculate @end_time a combination of g_get_current_time()
375 * and g_time_val_add() can be used.
377 * Return value: data from the queue or %NULL, when no data is
378 * received before @end_time.
381 g_async_queue_timed_pop_unlocked (GAsyncQueue
* queue
, GTimeVal
*end_time
)
383 g_return_val_if_fail (queue
, NULL
);
384 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, NULL
);
386 return g_async_queue_pop_intern_unlocked (queue
, FALSE
, end_time
);
390 * g_async_queue_length:
391 * @queue: a #GAsyncQueue.
393 * Returns the length of the queue, negative values mean waiting
394 * threads, positive values mean available entries in the
395 * @queue. Actually this function returns the number of data items in
396 * the queue minus the number of waiting threads. Thus a return value
397 * of 0 could mean 'n' entries in the queue and 'n' thread waiting.
398 * That can happen due to locking of the queue or due to
401 * Return value: the length of the @queue.
404 g_async_queue_length (GAsyncQueue
* queue
)
408 g_return_val_if_fail (queue
, 0);
409 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, 0);
411 g_mutex_lock (queue
->mutex
);
412 retval
= queue
->queue
->length
- queue
->waiting_threads
;
413 g_mutex_unlock (queue
->mutex
);
419 * g_async_queue_length_unlocked:
420 * @queue: a #GAsyncQueue.
422 * Returns the length of the queue, negative values mean waiting
423 * threads, positive values mean available entries in the
424 * @queue. Actually this function returns the number of data items in
425 * the queue minus the number of waiting threads. Thus a return value
426 * of 0 could mean 'n' entries in the queue and 'n' thread waiting.
427 * That can happen due to locking of the queue or due to
428 * scheduling. This function must be called while holding the @queue's
431 * Return value: the length of the @queue.
434 g_async_queue_length_unlocked (GAsyncQueue
* queue
)
436 g_return_val_if_fail (queue
, 0);
437 g_return_val_if_fail (g_atomic_int_get (&queue
->ref_count
) > 0, 0);
439 return queue
->queue
->length
- queue
->waiting_threads
;