From dd553a2ba32cd8523e3097d34228c21b96a3f10c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 8 Feb 2012 08:26:36 -0500 Subject: [PATCH] gasyncqueue: deprecate GTimeVal-based methods, add relative-delay ones https://bugzilla.gnome.org/show_bug.cgi?id=669670 --- docs/reference/glib/glib-sections.txt | 8 +- glib/gasyncqueue.c | 105 +++++++++++++++++++++++--- glib/gasyncqueue.h | 15 +++- glib/glib.symbols | 2 + glib/gthreadpool.c | 16 +--- 5 files changed, 117 insertions(+), 29 deletions(-) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 37a2709dc..0d87c4b2a 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -755,7 +755,7 @@ g_async_queue_push g_async_queue_push_sorted g_async_queue_pop g_async_queue_try_pop -g_async_queue_timed_pop +g_async_queue_timeout_pop g_async_queue_length g_async_queue_sort @@ -768,9 +768,13 @@ g_async_queue_push_unlocked g_async_queue_push_sorted_unlocked g_async_queue_pop_unlocked g_async_queue_try_pop_unlocked -g_async_queue_timed_pop_unlocked +g_async_queue_timeout_pop_unlocked g_async_queue_length_unlocked g_async_queue_sort_unlocked + + +g_async_queue_timed_pop +g_async_queue_timed_pop_unlocked
diff --git a/glib/gasyncqueue.c b/glib/gasyncqueue.c index 18c154cdc..195445e98 100644 --- a/glib/gasyncqueue.c +++ b/glib/gasyncqueue.c @@ -29,9 +29,11 @@ #include "gasyncqueue.h" #include "gasyncqueueprivate.h" +#include "gmain.h" #include "gmem.h" #include "gqueue.h" #include "gtestutils.h" +#include "gtimer.h" #include "gthread.h" #include "deprecated/gthread.h" @@ -67,7 +69,7 @@ * available in the queue at that point, the thread is now put to sleep * until a message arrives. The message will be removed from the queue * and returned. The functions g_async_queue_try_pop() and - * g_async_queue_timed_pop() can be used to only check for the presence + * g_async_queue_timeout_pop() can be used to only check for the presence * of messages or to only wait a certain time for messages respectively. * * For almost every function there exist two variants, one that locks @@ -406,7 +408,7 @@ g_async_queue_push_sorted_unlocked (GAsyncQueue *queue, static gpointer g_async_queue_pop_intern_unlocked (GAsyncQueue *queue, gboolean wait, - GTimeVal *end_time) + gint64 end_time) { gpointer retval; @@ -415,15 +417,20 @@ g_async_queue_pop_intern_unlocked (GAsyncQueue *queue, queue->waiting_threads++; while (!g_queue_peek_tail_link (&queue->queue)) { - if (!g_cond_timed_wait (&queue->cond, &queue->mutex, end_time)) - break; + if (end_time == -1) + g_cond_wait (&queue->cond, &queue->mutex); + else + { + if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time)) + break; + } } queue->waiting_threads--; } retval = g_queue_pop_tail (&queue->queue); - g_assert (retval || !wait || end_time); + g_assert (retval || !wait || end_time > 0); return retval; } @@ -445,7 +452,7 @@ g_async_queue_pop (GAsyncQueue *queue) g_return_val_if_fail (queue, NULL); g_mutex_lock (&queue->mutex); - retval = g_async_queue_pop_intern_unlocked (queue, TRUE, NULL); + retval = g_async_queue_pop_intern_unlocked (queue, TRUE, -1); g_mutex_unlock (&queue->mutex); return retval; @@ -467,7 +474,7 @@ g_async_queue_pop_unlocked (GAsyncQueue *queue) { g_return_val_if_fail (queue, NULL); - return g_async_queue_pop_intern_unlocked (queue, TRUE, NULL); + return g_async_queue_pop_intern_unlocked (queue, TRUE, -1); } /** @@ -488,7 +495,7 @@ g_async_queue_try_pop (GAsyncQueue *queue) g_return_val_if_fail (queue, NULL); g_mutex_lock (&queue->mutex); - retval = g_async_queue_pop_intern_unlocked (queue, FALSE, NULL); + retval = g_async_queue_pop_intern_unlocked (queue, FALSE, -1); g_mutex_unlock (&queue->mutex); return retval; @@ -511,7 +518,58 @@ g_async_queue_try_pop_unlocked (GAsyncQueue *queue) { g_return_val_if_fail (queue, NULL); - return g_async_queue_pop_intern_unlocked (queue, FALSE, NULL); + return g_async_queue_pop_intern_unlocked (queue, FALSE, -1); +} + +/** + * g_async_queue_timeout_pop: + * @queue: a #GAsyncQueue + * @timeout: the number of microseconds to wait + * + * Pops data from the @queue. If the queue is empty, blocks for + * @timeout microseconds, or until data becomes available. + * + * If no data is received before the timeout, %NULL is returned. + * + * Return value: data from the queue or %NULL, when no data is + * received before the timeout. + */ +gpointer +g_async_queue_timeout_pop (GAsyncQueue *queue, + guint64 timeout) +{ + gint64 end_time = g_get_monotonic_time () + timeout; + gpointer retval; + + g_mutex_lock (&queue->mutex); + retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); + g_mutex_unlock (&queue->mutex); + + return retval; +} + +/** + * g_async_queue_timeout_pop_unlocked: + * @queue: a #GAsyncQueue + * @time: the number of microseconds to wait + * + * Pops data from the @queue. If the queue is empty, blocks for + * @timeout microseconds, or until data becomes available. + * + * If no data is received before the timeout, %NULL is returned. + * + * This function must be called while holding the @queue's lock. + * + * Return value: data from the queue or %NULL, when no data is + * received before the timeout. + */ +gpointer +g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue, + guint64 timeout) +{ + gint64 end_time = g_get_monotonic_time () + timeout; + + return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); } /** @@ -529,17 +587,29 @@ g_async_queue_try_pop_unlocked (GAsyncQueue *queue) * * Return value: data from the queue or %NULL, when no data is * received before @end_time. + * + * Deprecated: use g_async_queue_timeout_pop(). */ gpointer g_async_queue_timed_pop (GAsyncQueue *queue, GTimeVal *end_time) { + gint64 m_end_time; gpointer retval; g_return_val_if_fail (queue, NULL); + if (end_time != NULL) + { + m_end_time = g_get_monotonic_time () + + (end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - + g_get_real_time ()); + } + else + m_end_time = -1; + g_mutex_lock (&queue->mutex); - retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); + retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time); g_mutex_unlock (&queue->mutex); return retval; @@ -562,14 +632,27 @@ g_async_queue_timed_pop (GAsyncQueue *queue, * * Return value: data from the queue or %NULL, when no data is * received before @end_time. + * + * Deprecated: use g_async_queue_timeout_pop_unlocked(). */ gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue, GTimeVal *end_time) { + gint64 m_end_time; + g_return_val_if_fail (queue, NULL); - return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); + if (end_time != NULL) + { + m_end_time = g_get_monotonic_time () + + (end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec - + g_get_real_time ()); + } + else + m_end_time = -1; + + return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time); } /** diff --git a/glib/gasyncqueue.h b/glib/gasyncqueue.h index e8fd0bfe6..f0d6d959a 100644 --- a/glib/gasyncqueue.h +++ b/glib/gasyncqueue.h @@ -66,10 +66,10 @@ gpointer g_async_queue_pop (GAsyncQueue *queue); gpointer g_async_queue_pop_unlocked (GAsyncQueue *queue); gpointer g_async_queue_try_pop (GAsyncQueue *queue); gpointer g_async_queue_try_pop_unlocked (GAsyncQueue *queue); -gpointer g_async_queue_timed_pop (GAsyncQueue *queue, - GTimeVal *end_time); -gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue, - GTimeVal *end_time); +gpointer g_async_queue_timeout_pop (GAsyncQueue *queue, + guint64 timeout); +gpointer g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue, + guint64 timeout); gint g_async_queue_length (GAsyncQueue *queue); gint g_async_queue_length_unlocked (GAsyncQueue *queue); void g_async_queue_sort (GAsyncQueue *queue, @@ -79,6 +79,13 @@ void g_async_queue_sort_unlocked (GAsyncQueue *queue, GCompareDataFunc func, gpointer user_data); +GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop) +gpointer g_async_queue_timed_pop (GAsyncQueue *queue, + GTimeVal *end_time); +GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop_unlocked) +gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue, + GTimeVal *end_time); + G_END_DECLS #endif /* __G_ASYNCQUEUE_H__ */ diff --git a/glib/glib.symbols b/glib/glib.symbols index d13420f39..6c2db0da6 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -80,6 +80,8 @@ g_async_queue_sort g_async_queue_sort_unlocked g_async_queue_timed_pop g_async_queue_timed_pop_unlocked +g_async_queue_timeout_pop +g_async_queue_timeout_pop_unlocked g_async_queue_try_pop g_async_queue_try_pop_unlocked g_async_queue_unlock diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c index b5e7dec82..de5b9de01 100644 --- a/glib/gthreadpool.c +++ b/glib/gthreadpool.c @@ -163,15 +163,11 @@ g_thread_pool_wait_for_new_pool (void) else if (local_max_idle_time > 0) { /* If a maximal idle time is given, wait for the given time. */ - GTimeVal end_time; - - g_get_current_time (&end_time); - g_time_val_add (&end_time, local_max_idle_time * 1000); - DEBUG_MSG (("thread %p waiting in global pool for %f seconds.", g_thread_self (), local_max_idle_time / 1000.0)); - pool = g_async_queue_timed_pop (unused_thread_queue, &end_time); + pool = g_async_queue_timeout_pop (unused_thread_queue, + local_max_idle_time * 1000); } else { @@ -260,17 +256,13 @@ g_thread_pool_wait_for_new_task (GRealThreadPool *pool) /* A thread will wait for new tasks for at most 1/2 * second before going to the global pool. */ - GTimeVal end_time; - - g_get_current_time (&end_time); - g_time_val_add (&end_time, G_USEC_PER_SEC / 2); /* 1/2 second */ - DEBUG_MSG (("thread %p in pool %p waits for up to a 1/2 second for task " "(%d running, %d unprocessed).", g_thread_self (), pool, pool->num_threads, g_async_queue_length_unlocked (pool->queue))); - task = g_async_queue_timed_pop_unlocked (pool->queue, &end_time); + task = g_async_queue_timeout_pop_unlocked (pool->queue, + G_USEC_PER_SEC / 2); } } else