*/
#include <string.h>
+
+#include "gst_private.h"
+
#include <gst/gst.h>
#include "gstatomicqueue.h"
+/**
+ * SECTION:gstatomicqueue
+ * @title: GstAtomicQueue
+ * @short_description: An atomic queue implementation
+ *
+ * The #GstAtomicQueue object implements a queue that can be used from multiple
+ * threads without performing any blocking operations.
+ *
+ * Since: 0.10.33
+ */
+
/* By default the queue uses 2 * sizeof(gpointer) * clp2 (max_items) of
* memory. clp2(x) is the next power of two >= than x.
*
struct _GstAtomicQueue
{
+ volatile gint refcount;
#ifdef LOW_MEM
gint num_readers;
#endif
}
}
+/**
+ * gst_atomic_queue_new:
+ * @initial_size: initial queue size
+ *
+ * Create a new atomic queue instance. @initial_size will be rounded up to the
+ * nearest power of 2 and used as the initial size of the queue.
+ *
+ * Returns: a new #GstAtomicQueue
+ *
+ * Since: 0.10.33
+ */
GstAtomicQueue *
gst_atomic_queue_new (guint initial_size)
{
queue = g_new (GstAtomicQueue, 1);
+ queue->refcount = 1;
#ifdef LOW_MEM
queue->num_readers = 0;
#endif
return queue;
}
+/**
+ * gst_atomic_queue_ref:
+ * @queue: a #GstAtomicQueue
+ *
+ * Increase the refcount of @queue.
+ */
void
+gst_atomic_queue_ref (GstAtomicQueue * queue)
+{
+ g_return_if_fail (queue != NULL);
+
+ g_atomic_int_inc (&queue->refcount);
+}
+
+static void
gst_atomic_queue_free (GstAtomicQueue * queue)
{
free_queue_mem (queue->head_mem);
g_free (queue);
}
+/**
+ * gst_atomic_queue_unref:
+ * @queue: a #GstAtomicQueue
+ *
+ * Unref @queue and free the memory when the refcount reaches 0.
+ */
+void
+gst_atomic_queue_unref (GstAtomicQueue * queue)
+{
+ g_return_if_fail (queue != NULL);
+
+ if (g_atomic_int_dec_and_test (&queue->refcount))
+ gst_atomic_queue_free (queue);
+}
+
+/**
+ * gst_atomic_queue_peek:
+ * @queue: a #GstAtomicQueue
+ *
+ * Peek the head element of the queue without removing it from the queue.
+ *
+ * Returns: the head element of @queue or NULL when the queue is empty.
+ */
gpointer
gst_atomic_queue_peek (GstAtomicQueue * queue)
{
GstAQueueMem *head_mem;
gint head, tail, size;
+ g_return_val_if_fail (queue != NULL, NULL);
+
while (TRUE) {
GstAQueueMem *next;
return head_mem->array[head & size];
}
+/**
+ * gst_atomic_queue_pop:
+ * @queue: a #GstAtomicQueue
+ *
+ * Get the head element of the queue.
+ *
+ * Returns: the head element of @queue or NULL when the queue is empty.
+ */
gpointer
gst_atomic_queue_pop (GstAtomicQueue * queue)
{
GstAQueueMem *head_mem;
gint head, tail, size;
+ g_return_val_if_fail (queue != NULL, NULL);
+
#ifdef LOW_MEM
g_atomic_int_inc (&queue->num_readers);
#endif
return ret;
}
+/**
+ * gst_atomic_queue_push:
+ * @queue: a #GstAtomicQueue
+ * @data: the data
+ *
+ * Append @data to the tail of the queue.
+ */
void
gst_atomic_queue_push (GstAtomicQueue * queue, gpointer data)
{
GstAQueueMem *tail_mem;
gint head, tail, size;
+ g_return_if_fail (queue != NULL);
+
do {
while (TRUE) {
GstAQueueMem *mem;
tail_mem->array[tail & size] = data;
}
+/**
+ * gst_atomic_queue_length:
+ * @queue: a #GstAtomicQueue
+ * @data: the data
+ *
+ * Get the amount of items in the queue.
+ *
+ * Returns: the number of elements in the queue.
+ */
guint
gst_atomic_queue_length (GstAtomicQueue * queue)
{
GstAQueueMem *head_mem, *tail_mem;
gint head, tail;
+ g_return_val_if_fail (queue != NULL, 0);
+
#ifdef LOW_MEM
g_atomic_int_inc (&queue->num_readers);
#endif
#ifndef __GST_ATOMIC_QUEUE_H__
#define __GST_ATOMIC_QUEUE_H__
+G_BEGIN_DECLS
+
+/**
+ * GstAtomicQueue:
+ * Opaque atomic data queue.
+ *
+ * Use the acessor functions to get the stored values.
+ */
typedef struct _GstAtomicQueue GstAtomicQueue;
-G_BEGIN_DECLS
GstAtomicQueue * gst_atomic_queue_new (guint initial_size);
-void gst_atomic_queue_free (GstAtomicQueue * queue);
+
+void gst_atomic_queue_ref (GstAtomicQueue * queue);
+void gst_atomic_queue_unref (GstAtomicQueue * queue);
void gst_atomic_queue_push (GstAtomicQueue* queue, gpointer data);
gpointer gst_atomic_queue_pop (GstAtomicQueue* queue);