#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"
* 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
static gpointer
g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
gboolean wait,
- GTimeVal *end_time)
+ gint64 end_time)
{
gpointer retval;
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;
}
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;
{
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);
}
/**
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;
{
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);
}
/**
*
* 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;
*
* 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);
}
/**
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
{
/* 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