Asynchronous Queues

## Asynchronous Queues Asynchronous Queues — asynchronous communication between threads |

## Synopsis

    #include <glib.h>

                        GAsyncQueue;
    GAsyncQueue *       g_async_queue_new                   (void);
    GAsyncQueue *       g_async_queue_new_full              (GDestroyNotify item_free_func);
    GAsyncQueue *       g_async_queue_ref                   (GAsyncQueue *queue);
    void                g_async_queue_unref                 (GAsyncQueue *queue);
    void                g_async_queue_push                  (GAsyncQueue *queue,
                                                             gpointer data);
    void                g_async_queue_push_sorted           (GAsyncQueue *queue,
                                                             gpointer data,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);
    gpointer            g_async_queue_pop                   (GAsyncQueue *queue);
    gpointer            g_async_queue_try_pop               (GAsyncQueue *queue);
    gpointer            g_async_queue_timeout_pop           (GAsyncQueue *queue,
                                                             guint64 timeout);
    gint                g_async_queue_length                (GAsyncQueue *queue);
    void                g_async_queue_sort                  (GAsyncQueue *queue,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

    void                g_async_queue_lock                  (GAsyncQueue *queue);
    void                g_async_queue_unlock                (GAsyncQueue *queue);
    void                g_async_queue_ref_unlocked          (GAsyncQueue *queue);
    void                g_async_queue_unref_and_unlock      (GAsyncQueue *queue);
    void                g_async_queue_push_unlocked         (GAsyncQueue *queue,
                                                             gpointer data);
    void                g_async_queue_push_sorted_unlocked  (GAsyncQueue *queue,
                                                             gpointer data,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);
    gpointer            g_async_queue_pop_unlocked          (GAsyncQueue *queue);
    gpointer            g_async_queue_try_pop_unlocked      (GAsyncQueue *queue);
    gpointer            g_async_queue_timeout_pop_unlocked  (GAsyncQueue *queue,
                                                             guint64 timeout);
    gint                g_async_queue_length_unlocked       (GAsyncQueue *queue);
    void                g_async_queue_sort_unlocked         (GAsyncQueue *queue,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

    gpointer            g_async_queue_timed_pop             (GAsyncQueue *queue,
                                                             GTimeVal *end_time);
    gpointer            g_async_queue_timed_pop_unlocked    (GAsyncQueue *queue,
                                                             GTimeVal *end_time);

## Description

Often you need to communicate between different threads. In general it's safer not to do this by shared memory, but by explicit message passing. These messages only make sense asynchronously for multi-threaded applications though, as a synchronous operation could as well be done in the same thread.

Asynchronous queues are an exception from most other GLib data structures, as they can be used simultaneously from multiple threads without explicit locking and they bring their own builtin reference counting. This is because the nature of an asynchronous queue is that it will always be used by at least 2 concurrent threads.

For using an asynchronous queue you first have to create one with `g_async_queue_new()`. GAsyncQueue structs are reference counted, use `g_async_queue_ref()` and `g_async_queue_unref()` to manage your references.

A thread which wants to send a message to that queue simply calls `g_async_queue_push()` to push the message to the queue.

A thread which is expecting messages from an asynchronous queue simply calls `g_async_queue_pop()` for that queue. If no message is 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_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 the queue and one that doesn't. That way you can hold the queue lock (acquire it with `g_async_queue_lock()` and release it with `g_async_queue_unlock()`) over multiple queue accessing instructions. This can be necessary to ensure the integrity of the queue, but should only be used when really necessary, as it can make your life harder if used unwisely. Normally you should only use the locking function variants (those without the _unlocked suffix).

In many cases, it may be more convenient to use GThreadPool when you need to distribute work to a set of worker threads instead of using GAsyncQueue manually. GThreadPool uses a GAsyncQueue internally.

## Details

### GAsyncQueue

    typedef struct _GAsyncQueue GAsyncQueue;

The GAsyncQueue struct is an opaque data structure which represents an asynchronous queue. It should only be accessed through the `g_async_queue_*` functions.

### g_async_queue_new ()

    GAsyncQueue *       g_async_queue_new                   (void);

Creates a new asynchronous queue.

Returns : | a new GAsyncQueue. Free with `g_async_queue_unref()`

### g_async_queue_new_full ()

    GAsyncQueue *       g_async_queue_new_full              (GDestroyNotify item_free_func);

Creates a new asynchronous queue and sets up a destroy notify function that is used to free any remaining queue items when the queue is destroyed after the final unref.

`item_free_func` : | function to free queue elements
Returns : | a new GAsyncQueue. Free with `g_async_queue_unref()`

Since 2.16

### g_async_queue_ref ()

    GAsyncQueue *       g_async_queue_ref                   (GAsyncQueue *queue);

Increases the reference count of the asynchronous `queue` by 1. You do not need to hold the lock to call this function.

`queue` : | a GAsyncQueue
Returns : | the `queue` that was passed in (since 2.6)

### g_async_queue_unref ()

    void                g_async_queue_unref                 (GAsyncQueue *queue);

Decreases the reference count of the asynchronous `queue` by 1.

If the reference count went to 0, the `queue` will be destroyed and the memory allocated will be freed. So you are not allowed to use the `queue` afterwards, as it might have disappeared. You do not need to hold the lock to call this function.

`queue` : | a GAsyncQueue.

### g_async_queue_push ()

    void                g_async_queue_push                  (GAsyncQueue *queue,
                                                             gpointer data);

Pushes the `data` into the `queue`. `data` must not be `NULL`.

`queue` : | a GAsyncQueue
`data` : | `data` to push into the `queue`

### g_async_queue_push_sorted ()

    void                g_async_queue_push_sorted           (GAsyncQueue *queue,
                                                             gpointer data,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

Inserts `data` into `queue` using `func` to determine the new position.

This function requires that the `queue` is sorted before pushing on new elements, see `g_async_queue_sort()`.

This function will lock `queue` before it sorts the queue and unlock it when it is finished.

For an example of `func` see `g_async_queue_sort()`.

`queue` : | a GAsyncQueue
`data` : | the `data` to push into the `queue`
`func` : | the GCompareDataFunc is used to sort `queue`
`user_data` : | user data passed to `func`.

Since 2.10

### g_async_queue_pop ()

    gpointer            g_async_queue_pop                   (GAsyncQueue *queue);

Pops data from the `queue`. If `queue` is empty, this function blocks until data becomes available.

`queue` : | a GAsyncQueue
Returns : | data from the queue

### g_async_queue_try_pop ()

    gpointer            g_async_queue_try_pop               (GAsyncQueue *queue);

Tries to pop data from the `queue`. If no data is available, `NULL` is returned.

`queue` : | a GAsyncQueue
Returns : | data from the queue or `NULL`, when no data is available immediately.

### g_async_queue_timeout_pop ()

    gpointer            g_async_queue_timeout_pop           (GAsyncQueue *queue,
                                                             guint64 timeout);

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.

`queue` : | a GAsyncQueue
`timeout` : | the number of microseconds to wait
Returns : | data from the queue or `NULL`, when no data is received before the timeout.

### g_async_queue_length ()

    gint                g_async_queue_length                (GAsyncQueue *queue);

Returns the length of the queue.

Actually this function returns the number of data items in the queue minus the number of waiting threads, so a negative value means waiting threads, and a positive value means available entries in the `queue`. A return value of 0 could mean n entries in the queue and n threads waiting. This can happen due to locking of the queue or due to scheduling.

`queue` : | a GAsyncQueue.
Returns : | the length of the `queue`

### g_async_queue_sort ()

    void                g_async_queue_sort                  (GAsyncQueue *queue,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

Sorts `queue` using `func`.

The sort function `func` is passed two elements of the `queue`. It should return 0 if they are equal, a negative value if the first element should be higher in the `queue` or a positive value if the first element should be lower in the `queue` than the second element.

This function will lock `queue` before it sorts the queue and unlock it when it is finished.

If you were sorting a list of priority numbers to make sure the lowest priority would be at the top of the queue, you could use:

    1
    2
    3
    4
    5
    6
    7
    gint32 id1;
    gint32 id2;

    id1 = GPOINTER_TO_INT (element1);
    id2 = GPOINTER_TO_INT (element2);

    return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);

`queue` : | a GAsyncQueue
`func` : | the GCompareDataFunc is used to sort `queue`
`user_data` : | user data passed to `func`

Since 2.10

### g_async_queue_lock ()

    void                g_async_queue_lock                  (GAsyncQueue *queue);

Acquires the `queue`'s lock. If another thread is already holding the lock, this call will block until the lock becomes available.

Call `g_async_queue_unlock()` to drop the lock again.

While holding the lock, you can only call the `g_async_queue_*_unlocked()` functions on `queue`. Otherwise, deadlock may occur.

`queue` : | a GAsyncQueue

### g_async_queue_unlock ()

    void                g_async_queue_unlock                (GAsyncQueue *queue);

Releases the queue's lock.

Calling this function when you have not acquired the with `g_async_queue_lock()` leads to undefined behaviour.

`queue` : | a GAsyncQueue

### g_async_queue_ref_unlocked ()

    void                g_async_queue_ref_unlocked          (GAsyncQueue *queue);

### Warning

`g_async_queue_ref_unlocked` has been deprecated since version 2.8 and should not be used in newly-written code. Reference counting is done atomically. so `g_async_queue_ref()` can be used regardless of the `queue`'s lock.

Increases the reference count of the asynchronous `queue` by 1.

`queue` : | a GAsyncQueue

### g_async_queue_unref_and_unlock ()

    void                g_async_queue_unref_and_unlock      (GAsyncQueue *queue);

### Warning

`g_async_queue_unref_and_unlock` has been deprecated since version 2.8 and should not be used in newly-written code. Reference counting is done atomically. so `g_async_queue_unref()` can be used regardless of the `queue`'s lock.

Decreases the reference count of the asynchronous `queue` by 1 and releases the lock. This function must be called while holding the `queue`'s lock. If the reference count went to 0, the `queue` will be destroyed and the memory allocated will be freed.

`queue` : | a GAsyncQueue

### g_async_queue_push_unlocked ()

    void                g_async_queue_push_unlocked         (GAsyncQueue *queue,
                                                             gpointer data);

Pushes the `data` into the `queue`. `data` must not be `NULL`.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
`data` : | `data` to push into the `queue`

### g_async_queue_push_sorted_unlocked ()

    void                g_async_queue_push_sorted_unlocked  (GAsyncQueue *queue,
                                                             gpointer data,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

Inserts `data` into `queue` using `func` to determine the new position.

The sort function `func` is passed two elements of the `queue`. It should return 0 if they are equal, a negative value if the first element should be higher in the `queue` or a positive value if the first element should be lower in the `queue` than the second element.

This function requires that the `queue` is sorted before pushing on new elements, see `g_async_queue_sort()`.

This function must be called while holding the `queue`'s lock.

For an example of `func` see `g_async_queue_sort()`.

`queue` : | a GAsyncQueue
`data` : | the `data` to push into the `queue`
`func` : | the GCompareDataFunc is used to sort `queue`
`user_data` : | user data passed to `func`.

Since 2.10

### g_async_queue_pop_unlocked ()

    gpointer            g_async_queue_pop_unlocked          (GAsyncQueue *queue);

Pops data from the `queue`. If `queue` is empty, this function blocks until data becomes available.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
Returns : | data from the queue.

### g_async_queue_try_pop_unlocked ()

    gpointer            g_async_queue_try_pop_unlocked      (GAsyncQueue *queue);

Tries to pop data from the `queue`. If no data is available, `NULL` is returned.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
Returns : | data from the queue or `NULL`, when no data is available immediately.

### g_async_queue_timeout_pop_unlocked ()

    gpointer            g_async_queue_timeout_pop_unlocked  (GAsyncQueue *queue,
                                                             guint64 timeout);

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.

`queue` : | a GAsyncQueue
`timeout` : | the number of microseconds to wait
Returns : | data from the queue or `NULL`, when no data is received before the timeout.

### g_async_queue_length_unlocked ()

    gint                g_async_queue_length_unlocked       (GAsyncQueue *queue);

Returns the length of the queue.

Actually this function returns the number of data items in the queue minus the number of waiting threads, so a negative value means waiting threads, and a positive value means available entries in the `queue`. A return value of 0 could mean n entries in the queue and n threads waiting. This can happen due to locking of the queue or due to scheduling.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
Returns : | the length of the `queue`.

### g_async_queue_sort_unlocked ()

    void                g_async_queue_sort_unlocked         (GAsyncQueue *queue,
                                                             GCompareDataFunc func,
                                                             gpointer user_data);

Sorts `queue` using `func`.

The sort function `func` is passed two elements of the `queue`. It should return 0 if they are equal, a negative value if the first element should be higher in the `queue` or a positive value if the first element should be lower in the `queue` than the second element.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
`func` : | the GCompareDataFunc is used to sort `queue`
`user_data` : | user data passed to `func`

Since 2.10

### g_async_queue_timed_pop ()

    gpointer            g_async_queue_timed_pop             (GAsyncQueue *queue,
                                                             GTimeVal *end_time);

### Warning

`g_async_queue_timed_pop` is deprecated and should not be used in newly-written code. use `g_async_queue_timeout_pop()`.

Pops data from the `queue`. If the queue is empty, blocks until `end_time` or until data becomes available.

If no data is received before `end_time`, `NULL` is returned.

To easily calculate `end_time`, a combination of `g_get_current_time()` and `g_time_val_add()` can be used.

`queue` : | a GAsyncQueue
`end_time` : | a GTimeVal, determining the final time
Returns : | data from the queue or `NULL`, when no data is received before `end_time`.

### g_async_queue_timed_pop_unlocked ()

    gpointer            g_async_queue_timed_pop_unlocked    (GAsyncQueue *queue,
                                                             GTimeVal *end_time);

### Warning

`g_async_queue_timed_pop_unlocked` is deprecated and should not be used in newly-written code. use `g_async_queue_timeout_pop_unlocked()`.

Pops data from the `queue`. If the queue is empty, blocks until `end_time` or until data becomes available.

If no data is received before `end_time`, `NULL` is returned.

To easily calculate `end_time`, a combination of `g_get_current_time()` and `g_time_val_add()` can be used.

This function must be called while holding the `queue`'s lock.

`queue` : | a GAsyncQueue
`end_time` : | a GTimeVal, determining the final time
Returns : | data from the queue or `NULL`, when no data is received before `end_time`.

## See Also

GThreadPool