mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
libs: New growing-only queue.
This is a queue which has the same API as GQueue, except that: * It uses an array, instead of a doubled-linked-list * The array can only grow. This code is not-threadsafe. It is up to the owner to make sure the proper locking is taken before calling this API.
This commit is contained in:
parent
49ea16e041
commit
588cdcd369
4 changed files with 219 additions and 2 deletions
|
@ -13,7 +13,8 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \
|
|||
gstbytewriter.c \
|
||||
gstcollectpads.c \
|
||||
gstpushsrc.c \
|
||||
gsttypefindhelper.c
|
||||
gsttypefindhelper.c \
|
||||
gstqueuearray.c
|
||||
|
||||
libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS)
|
||||
libgstbase_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS)
|
||||
|
@ -33,7 +34,8 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \
|
|||
gstbytewriter.h \
|
||||
gstcollectpads.h \
|
||||
gstpushsrc.h \
|
||||
gsttypefindhelper.h
|
||||
gsttypefindhelper.h \
|
||||
gstqueuearray.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
gstbytereader-docs.h \
|
||||
|
|
162
libs/gst/base/gstqueuearray.c
Normal file
162
libs/gst/base/gstqueuearray.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
|
||||
*
|
||||
* gstqueuearray.c:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/gst.h>
|
||||
#include "gstqueuearray.h"
|
||||
|
||||
GstQueueArray *
|
||||
gst_queue_array_new (guint initial_size)
|
||||
{
|
||||
GstQueueArray *array = g_malloc (sizeof (GstQueueArray));
|
||||
|
||||
array->size = initial_size;
|
||||
array->array = g_new0 (gpointer, initial_size);
|
||||
array->head = 0;
|
||||
array->tail = 0;
|
||||
array->length = 0;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
gpointer
|
||||
gst_queue_array_pop_head (GstQueueArray * array)
|
||||
{
|
||||
gpointer ret;
|
||||
|
||||
/* empty array */
|
||||
if (G_UNLIKELY (array->length == 0))
|
||||
return NULL;
|
||||
ret = array->array[array->head];
|
||||
array->head++;
|
||||
array->head %= array->size;
|
||||
array->length--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
|
||||
{
|
||||
/* Check if we need to make room */
|
||||
if (G_UNLIKELY (array->length == array->size)) {
|
||||
/* newsize is 50% bigger */
|
||||
guint newsize = (3 * array->size) / 2;
|
||||
|
||||
/* copy over data */
|
||||
if (array->tail != 0) {
|
||||
gpointer *array2 = g_new0 (gpointer, newsize);
|
||||
guint t1 = array->head;
|
||||
guint t2 = array->size - array->head;
|
||||
|
||||
/* [0-----TAIL][HEAD------SIZE]
|
||||
*
|
||||
* We want to end up with
|
||||
* [HEAD------------------TAIL][----FREEDATA------NEWSIZE]
|
||||
*
|
||||
* 1) move [HEAD-----SIZE] part to beginning of new array
|
||||
* 2) move [0-------TAIL] part new array, after previous part
|
||||
*/
|
||||
|
||||
memcpy (array2, &array->array[array->head], t2 * sizeof (gpointer));
|
||||
memcpy (&array2[t2], array->array, t1 * sizeof (gpointer));
|
||||
|
||||
g_free (array->array);
|
||||
array->array = array2;
|
||||
array->head = 0;
|
||||
} else {
|
||||
/* Fast path, we just need to grow the array */
|
||||
array->array = g_renew (gpointer, array->array, newsize);
|
||||
}
|
||||
array->tail = array->size;
|
||||
array->size = newsize;
|
||||
}
|
||||
|
||||
array->array[array->tail] = data;
|
||||
array->tail++;
|
||||
array->tail %= array->size;
|
||||
array->length++;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_queue_array_is_empty (GstQueueArray * array)
|
||||
{
|
||||
return (array->length == 0);
|
||||
}
|
||||
|
||||
void
|
||||
gst_queue_array_free (GstQueueArray * array)
|
||||
{
|
||||
g_free (array->array);
|
||||
g_free (array);
|
||||
}
|
||||
|
||||
void
|
||||
gst_queue_array_drop_element (GstQueueArray * array, guint idx)
|
||||
{
|
||||
if (idx == array->head) {
|
||||
/* just move the head */
|
||||
array->head++;
|
||||
array->head %= array->size;
|
||||
return;
|
||||
}
|
||||
if (idx == array->tail - 1) {
|
||||
/* just move the tail */
|
||||
array->tail = (array->tail - 1 + array->size) % array->size;
|
||||
return;
|
||||
}
|
||||
/* drop the element #idx... and readjust the array */
|
||||
if (array->head < array->tail) {
|
||||
/* Make sure it's within the boundaries */
|
||||
g_assert (array->head < idx && idx <= array->tail);
|
||||
/* ends not wrapped */
|
||||
/* move head-idx to head+1 */
|
||||
memcpy (&array->array[array->head + 1],
|
||||
&array->array[array->head], (idx - array->head) * sizeof (gpointer));
|
||||
array->tail--;
|
||||
} else {
|
||||
/* ends are wrapped */
|
||||
if (idx < array->tail) {
|
||||
/* move idx-tail backwards one */
|
||||
memcpy (&array->array[idx - 1],
|
||||
&array->array[idx], (array->tail - idx) * sizeof (gpointer));
|
||||
array->tail--;
|
||||
} else if (idx >= array->head) {
|
||||
/* move head-idx forwards one */
|
||||
memcpy (&array->array[array->head],
|
||||
&array->array[array->head + 1],
|
||||
(idx - array->head) * sizeof (gpointer));
|
||||
array->head++;
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* Scan from head to tail */
|
||||
for (i = array->head; i < array->length; i = (i + 1) % array->size)
|
||||
if (func (array->array[i], data) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
48
libs/gst/base/gstqueuearray.h
Normal file
48
libs/gst/base/gstqueuearray.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2009-2010 Edward Hervey <bilboed@bilboed.com>
|
||||
*
|
||||
* gstqueuearray.h:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifndef __GST_QUEUE_ARRAY_H__
|
||||
#define __GST_QUEUE_ARRAY_H__
|
||||
|
||||
typedef struct _GstQueueArray GstQueueArray;
|
||||
|
||||
struct _GstQueueArray
|
||||
{
|
||||
gpointer *array;
|
||||
guint size;
|
||||
guint head;
|
||||
guint tail;
|
||||
guint length;
|
||||
};
|
||||
|
||||
GstQueueArray *gst_queue_array_new (guint initial_size);
|
||||
gpointer gst_queue_array_pop_head (GstQueueArray * array);
|
||||
void gst_queue_array_push_tail (GstQueueArray * array, gpointer data);
|
||||
gboolean gst_queue_array_is_empty (GstQueueArray * array);
|
||||
void gst_queue_array_free (GstQueueArray * array);
|
||||
|
||||
void gst_queue_array_drop_element (GstQueueArray * array, guint idx);
|
||||
guint gst_queue_array_find (GstQueueArray * array, GCompareFunc func,
|
||||
gpointer data);
|
||||
|
||||
#endif
|
|
@ -237,6 +237,11 @@ EXPORTS
|
|||
gst_collect_pads_stop
|
||||
gst_collect_pads_take_buffer
|
||||
gst_push_src_get_type
|
||||
gst_queue_array_free
|
||||
gst_queue_array_is_empty
|
||||
gst_queue_array_new
|
||||
gst_queue_array_pop_head
|
||||
gst_queue_array_push_tail
|
||||
gst_type_find_helper
|
||||
gst_type_find_helper_for_buffer
|
||||
gst_type_find_helper_for_data
|
||||
|
|
Loading…
Reference in a new issue