+2005-09-26 Andy Wingo <wingo@pobox.com>
+
+ * configure.ac:
+ * tests/Makefile.am:
+ * tests/memchunk: Remove memchunk benchmark stuff, this is taken
+ over by GLib bug 118439.
+
+ * gst/base/gstbasesink.c (gst_base_sink_wait): Factor out the wait
+ routines to a function.
+
+ * docs/libs/gstreamer-libs-sections.txt: I am a good person today.
+
+ * libs/gst/controller/gsthelper.c:
+ * libs/gst/controller/gstcontroller.h (gst_controller_sync_values)
+ (gst_object_sync_values): Renamed from sink_values. Ugh.
+
+ * libs/gst/controller/gsthelper.c: Update for __gst_controller_key.
+
+ * libs/gst/controller/gstcontroller.c (__gst_controller_key):
+ Renamed from controller_key, as it is exported.
+
+ * gst/gstvalue.c (_gst_value_initialize): Fake out the compiler.
+
2005-09-26 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/Makefile.am:
check/Makefile
tests/Makefile
tests/instantiate/Makefile
-tests/memchunk/Makefile
tests/muxing/Makefile
tests/seeking/Makefile
tests/sched/Makefile
gst_controller_unset
gst_controller_get
gst_controller_get_all
-gst_controller_sink_values
+gst_controller_sync_values
gst_controller_get_value_arrays
gst_controller_get_value_array
gst_controller_set_interpolation_mode
gst_object_uncontrol_properties
gst_object_get_controller
gst_object_set_controller
-gst_object_sink_values
+gst_object_sync_values
gst_object_get_value_arrays
gst_object_get_value_array
<SUBSECTION Standard>
}
}
+/* with STREAM_LOCK and LOCK*/
+static GstClockReturn
+gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
+{
+ GstClockReturn ret;
+
+ /* clock_id should be NULL outside of this function */
+ g_assert (basesink->clock_id == NULL);
+ g_assert (GST_CLOCK_TIME_IS_VALID (time));
+
+ basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
+
+ /* release the object lock while waiting */
+ GST_UNLOCK (basesink);
+ ret = gst_clock_id_wait (basesink->clock_id, NULL);
+ GST_LOCK (basesink);
+
+ gst_clock_id_unref (basesink->clock_id);
+ basesink->clock_id = NULL;
+
+ return ret;
+}
+
/* perform synchronisation on a buffer
*
* 1) check if we have a clock, if not, do nothing
GstClockTime base_time;
GST_LOCK (basesink);
+
base_time = GST_ELEMENT (basesink)->base_time;
GST_LOG_OBJECT (basesink,
"waiting for clock, base time %" GST_TIME_FORMAT,
GST_TIME_ARGS (base_time));
- /* save clock id so that we can unlock it if needed */
- basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- stream_start + base_time);
/* also save end_time of this buffer so that we can wait
* to signal EOS */
if (end_valid)
basesink->end_time = stream_end + base_time;
else
basesink->end_time = GST_CLOCK_TIME_NONE;
- GST_UNLOCK (basesink);
- ret = gst_clock_id_wait (basesink->clock_id, NULL);
+ ret = gst_base_sink_wait (basesink, stream_start + base_time);
- GST_LOCK (basesink);
- if (basesink->clock_id) {
- gst_clock_id_unref (basesink->clock_id);
- basesink->clock_id = NULL;
- }
GST_UNLOCK (basesink);
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
if (basesink->clock) {
/* wait for last buffer to finish if we have a valid end time */
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
- basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- basesink->end_time);
- GST_UNLOCK (basesink);
-
- gst_clock_id_wait (basesink->clock_id, NULL);
-
- GST_LOCK (basesink);
- if (basesink->clock_id) {
- gst_clock_id_unref (basesink->clock_id);
- basesink->clock_id = NULL;
- }
+ gst_base_sink_wait (basesink, basesink->end_time);
basesink->end_time = GST_CLOCK_TIME_NONE;
}
}
gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
+#if GLIB_CHECK_VERSION(2,8,0)
+ /* see bug #317246 */
+ GST_LOG ("Faking out the compiler: %d", G_TYPE_DATE);
+#endif
+
gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
gst_value_union_int_int_range);
gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
}
}
+/* with STREAM_LOCK and LOCK*/
+static GstClockReturn
+gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
+{
+ GstClockReturn ret;
+
+ /* clock_id should be NULL outside of this function */
+ g_assert (basesink->clock_id == NULL);
+ g_assert (GST_CLOCK_TIME_IS_VALID (time));
+
+ basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
+
+ /* release the object lock while waiting */
+ GST_UNLOCK (basesink);
+ ret = gst_clock_id_wait (basesink->clock_id, NULL);
+ GST_LOCK (basesink);
+
+ gst_clock_id_unref (basesink->clock_id);
+ basesink->clock_id = NULL;
+
+ return ret;
+}
+
/* perform synchronisation on a buffer
*
* 1) check if we have a clock, if not, do nothing
GstClockTime base_time;
GST_LOCK (basesink);
+
base_time = GST_ELEMENT (basesink)->base_time;
GST_LOG_OBJECT (basesink,
"waiting for clock, base time %" GST_TIME_FORMAT,
GST_TIME_ARGS (base_time));
- /* save clock id so that we can unlock it if needed */
- basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- stream_start + base_time);
/* also save end_time of this buffer so that we can wait
* to signal EOS */
if (end_valid)
basesink->end_time = stream_end + base_time;
else
basesink->end_time = GST_CLOCK_TIME_NONE;
- GST_UNLOCK (basesink);
- ret = gst_clock_id_wait (basesink->clock_id, NULL);
+ ret = gst_base_sink_wait (basesink, stream_start + base_time);
- GST_LOCK (basesink);
- if (basesink->clock_id) {
- gst_clock_id_unref (basesink->clock_id);
- basesink->clock_id = NULL;
- }
GST_UNLOCK (basesink);
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
if (basesink->clock) {
/* wait for last buffer to finish if we have a valid end time */
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
- basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- basesink->end_time);
- GST_UNLOCK (basesink);
-
- gst_clock_id_wait (basesink->clock_id, NULL);
-
- GST_LOCK (basesink);
- if (basesink->clock_id) {
- gst_clock_id_unref (basesink->clock_id);
- basesink->clock_id = NULL;
- }
+ gst_base_sink_wait (basesink, basesink->end_time);
basesink->end_time = GST_CLOCK_TIME_NONE;
}
}
* </para></listitem>
* <listitem><para>
* when processing data (get, chain, loop function) at the beginning call
- * gst_object_sink_values(element,timestamp).
+ * gst_object_sync_values(element,timestamp).
* This will made the controller to update all gobject properties that are under
* control with the current values based on timestamp.
* </para></listitem>
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
static GObjectClass *parent_class = NULL;
-GQuark controller_key;
+GQuark __gst_controller_key;
/* imports from gst-interpolation.c */
GST_INFO ("notify for '%s'", prop->name);
- ctrl = g_object_get_qdata (G_OBJECT (object), controller_key);
+ ctrl = g_object_get_qdata (G_OBJECT (object), __gst_controller_key);
g_return_if_fail (ctrl);
if (g_mutex_trylock (ctrl->lock)) {
GstParent will be in core after all.
*/
- self = g_object_get_qdata (object, controller_key);
+ self = g_object_get_qdata (object, __gst_controller_key);
// create GstControlledProperty for each property
while ((name = va_arg (var_args, gchar *))) {
// test if this property isn't yet controlled
self = g_object_new (GST_TYPE_CONTROLLER, NULL);
self->object = object;
// store the controller
- g_object_set_qdata (object, controller_key, self);
+ g_object_set_qdata (object, __gst_controller_key, self);
} else {
// increment ref-count (this causes red-count-leaks
//self = g_object_ref (self);
}
/**
- * gst_controller_sink_values:
+ * gst_controller_sync_values:
* @self: the controller that handles the values
* @timestamp: the time that should be processed
*
* Since: 0.9
*/
gboolean
-gst_controller_sink_values (GstController * self, GstClockTime timestamp)
+gst_controller_sync_values (GstController * self, GstClockTime timestamp)
{
GstControlledProperty *prop;
GList *node;
g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- GST_INFO ("sink_values");
+ GST_INFO ("sync_values");
g_mutex_lock (self->lock);
// go over the controlled properties of the controller
}
g_mutex_free (self->lock);
/* remove controller from objects qdata list */
- g_object_set_qdata (self->object, controller_key, NULL);
+ g_object_set_qdata (self->object, __gst_controller_key, NULL);
if (G_OBJECT_CLASS (parent_class)->finalize)
(G_OBJECT_CLASS (parent_class)->finalize) (object);
gobject_class->finalize = _gst_controller_finalize;
- controller_key = g_quark_from_string ("gst::controller");
+ __gst_controller_key = g_quark_from_string ("gst::controller");
// register properties
// register signals
gchar * property_name);
-gboolean gst_controller_sink_values (GstController * self,
+gboolean gst_controller_sync_values (GstController * self,
GstClockTime timestamp);
gboolean gst_controller_get_value_arrays (GstController * self,
GstController *gst_object_get_controller (GObject * object);
gboolean gst_object_set_controller (GObject * object, GstController * controller);
-gboolean gst_object_sink_values (GObject * object, GstClockTime timestamp);
+gboolean gst_object_sync_values (GObject * object, GstClockTime timestamp);
gboolean gst_object_get_value_arrays (GObject * object,
GstClockTime timestamp, GSList * value_arrays);
#define GST_CAT_DEFAULT gst_controller_debug
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
-extern GQuark controller_key;
+extern GQuark __gst_controller_key;
/**
* gst_object_control_properties:
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
- if ((ctrl = g_object_get_qdata (object, controller_key))) {
+ if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
va_list var_args;
va_start (var_args, object);
{
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
- return (g_object_get_qdata (object, controller_key));
+ return (g_object_get_qdata (object, __gst_controller_key));
}
/**
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (controller, FALSE);
- if (!(ctrl = g_object_get_qdata (object, controller_key))) {
- g_object_set_qdata (object, controller_key, controller);
+ if (!(ctrl = g_object_get_qdata (object, __gst_controller_key))) {
+ g_object_set_qdata (object, __gst_controller_key, controller);
return (TRUE);
}
return (FALSE);
}
/**
- * gst_object_sink_values:
+ * gst_object_sync_values:
* @object: the object that has controlled properties
* @timestamp: the time that should be processed
*
* Convenience function for GObject
*
- * Returns: same thing as gst_controller_sink_values()
+ * Returns: same thing as gst_controller_sync_values()
* Since: 0.9
*/
gboolean
-gst_object_sink_values (GObject * object, GstClockTime timestamp)
+gst_object_sync_values (GObject * object, GstClockTime timestamp)
{
GstController *ctrl = NULL;
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- if ((ctrl = g_object_get_qdata (object, controller_key))) {
- return gst_controller_sink_values (ctrl, timestamp);
+ if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
+ return gst_controller_sync_values (ctrl, timestamp);
}
return (FALSE);
}
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- if ((ctrl = g_object_get_qdata (object, controller_key))) {
+ if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
return gst_controller_get_value_arrays (ctrl, timestamp, value_arrays);
}
return (FALSE);
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- if ((ctrl = g_object_get_qdata (object, controller_key))) {
+ if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
return gst_controller_get_value_array (ctrl, timestamp, value_array);
}
return (FALSE);
-SUBDIRS = instantiate memchunk muxing sched threadstate seeking
+SUBDIRS = instantiate muxing sched threadstate seeking
if GST_DISABLE_TRACE
LAT =
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la
EXTRA_DIST = README
-DIST_SUBDIRS= instantiate memchunk muxing sched threadstate seeking
+DIST_SUBDIRS= instantiate muxing sched threadstate seeking
+++ /dev/null
-gmemchunktest
-gstmemchunktest
-*.bb
-*.bbg
-*.da
+++ /dev/null
-noinst_PROGRAMS = gmemchunktest gstmemchunktest
-
-gmemchunktest_SOURCES = gmemchunktest.c
-gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
-
-LDADD = $(GST_OBJ_LIBS)
-AM_CFLAGS = $(GST_OBJ_CFLAGS)
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2005 Andy Wingo <wingo at pobox.com>
- *
- * 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 <stdlib.h>
-#include <glib.h>
-#include <gmodule.h>
-#include <gst/gstmemchunk.h>
-
-
-#define MAX_THREADS 100
-#define CHUNK_SIZE 32
-#define GMEMCHUNK_THREADSAFE
-
-
-typedef gpointer (*alloc_func_t) (void);
-typedef void (*free_func_t) (gpointer);
-
-
-static gint num_allocs;
-static gint num_threads;
-static alloc_func_t _alloc = NULL;
-static free_func_t _free = NULL;
-
-static GMemChunk *_gmemchunk;
-static GMutex *_gmemchunklock;
-static GstMemChunk *_gstmemchunk;
-
-static GCond *ready_cond;
-static GCond *start_cond;
-static GMutex *sync_mutex;
-
-
-static gdouble
-get_current_time (void)
-{
- GTimeVal tv;
-
- g_get_current_time (&tv);
- return tv.tv_sec + ((gdouble) tv.tv_usec) / G_USEC_PER_SEC;
-}
-
-
-/*
- * GMemChunk implementation
- */
-
-static gpointer
-gmemchunk_alloc (void)
-{
- gpointer ret;
-
-#ifdef GMEMCHUNK_THREADSAFE
- g_mutex_lock (_gmemchunklock);
-#endif
- ret = g_mem_chunk_alloc (_gmemchunk);
-#ifdef GMEMCHUNK_THREADSAFE
- g_mutex_unlock (_gmemchunklock);
-#endif
-
- return ret;
-}
-
-static void
-gmemchunk_free (gpointer chunk)
-{
-#ifdef GMEMCHUNK_THREADSAFE
- g_mutex_lock (_gmemchunklock);
-#endif
- g_mem_chunk_free (_gmemchunk, chunk);
-#ifdef GMEMCHUNK_THREADSAFE
- g_mutex_unlock (_gmemchunklock);
-#endif
-}
-
-/*
- * GstMemChunk implementation
- */
-
-static gpointer
-gstmemchunk_alloc (void)
-{
- return gst_mem_chunk_alloc (_gstmemchunk);
-}
-
-static void
-gstmemchunk_free (gpointer chunk)
-{
- gst_mem_chunk_free (_gstmemchunk, chunk);
-}
-
-/*
- * Normal (malloc/free) implementation
- */
-
-static gpointer
-normal_alloc (void)
-{
- return g_malloc (CHUNK_SIZE);
-}
-
-static void
-normal_free (gpointer chunk)
-{
- g_free (chunk);
-}
-
-/*
- * Normal (malloc/free) implementation
- */
-
-void *(*_google_malloc) (gsize) = NULL;
-void (*_google_free) (void *) = NULL;
-static gpointer
-google_alloc (void)
-{
- return _google_malloc (CHUNK_SIZE);
-}
-
-static void
-google_free (gpointer chunk)
-{
- _google_free (chunk);
-}
-
-/*
- * The test
- */
-
-void *
-worker_thread (void *threadid)
-{
- gint i;
- gpointer chunk;
-
- g_mutex_lock (sync_mutex);
- g_cond_signal (ready_cond);
- g_cond_wait (start_cond, sync_mutex);
- g_mutex_unlock (sync_mutex);
-
- for (i = 0; i < num_allocs; i++) {
- chunk = _alloc ();
- _free (chunk);
- }
-
- return NULL;
-}
-
-gdouble
-run_test (alloc_func_t alloc_func, free_func_t free_func)
-{
- gdouble start, end;
- GThread *threads[MAX_THREADS];
- GError *error;
- int t;
-
- _alloc = alloc_func;
- _free = free_func;
-
- g_mutex_lock (sync_mutex);
- for (t = 0; t < num_threads; t++) {
- error = NULL;
- threads[t] =
- g_thread_create (worker_thread, GINT_TO_POINTER (t), TRUE, &error);
- g_assert (threads[t]);
- g_cond_wait (ready_cond, sync_mutex);
- }
-
- g_cond_broadcast (start_cond);
- start = get_current_time ();
- g_mutex_unlock (sync_mutex);
-
- for (t = 0; t < num_threads; t++)
- g_thread_join (threads[t]);
-
- end = get_current_time ();
-
- return end - start;
-}
-
-gint
-main (gint argc, gchar * argv[])
-{
- gdouble time;
- GModule *google_lib;
-
- g_thread_init (NULL);
-
- ready_cond = g_cond_new ();
- start_cond = g_cond_new ();
- sync_mutex = g_mutex_new ();
-
- if (argc != 3) {
- g_print ("usage: %s <num_threads> <num_allocs>\n", argv[0]);
- exit (-1);
- }
-
- num_threads = atoi (argv[1]);
- num_allocs = atoi (argv[2]);
- g_assert (num_threads > 0);
- g_assert (num_allocs > 0);
-
- _gmemchunk =
- g_mem_chunk_new ("test", CHUNK_SIZE, CHUNK_SIZE * 16, G_ALLOC_ONLY);
- _gmemchunklock = g_mutex_new ();
- _gstmemchunk =
- gst_mem_chunk_new ("test", CHUNK_SIZE, CHUNK_SIZE * 16, G_ALLOC_ONLY);
-
- g_print ("%d alloc+frees X %d threads\n", num_allocs, num_threads);
- time = run_test (gmemchunk_alloc, gmemchunk_free);
- g_print ("%fs (%fs/thread) - GMemChunk\n", time, time / num_threads);
- time = run_test (gstmemchunk_alloc, gstmemchunk_free);
- g_print ("%fs (%fs/thread) - GstMemChunk\n", time, time / num_threads);
- time = run_test (normal_alloc, normal_free);
- g_print ("%fs (%fs/thread) - g_malloc/g_free\n", time, time / num_threads);
-
- google_lib = g_module_open ("libtcmalloc.so", G_MODULE_BIND_LOCAL);
- if (google_lib) {
- gpointer sym;
-
- g_module_symbol (google_lib, "malloc", &sym);
- g_assert (sym);
- _google_malloc = sym;
- g_module_symbol (google_lib, "free", &sym);
- g_assert (sym);
- _google_free = sym;
- time = run_test (google_alloc, google_free);
- g_print ("%fs (%fs/thread) - google malloc/free\n", time,
- time / num_threads);
- } else {
- g_print ("google malloc unavailable: %s\n", g_module_error ());
- }
-
- /* g_mem_chunk_info (); */
- return 0;
-}
+++ /dev/null
-#include <string.h> /* memset */
-#include <stdlib.h> /* memset */
-#include "gstmemchunk.h"
-
-#ifdef __SMP__
-#define CHUNK_LOCK "lock ; "
-#else
-#define CHUNK_LOCK ""
-#endif
-
-#define GST_MEM_CHUNK_AREA(chunk) (((GstMemChunkElement*)(chunk))->area)
-#define GST_MEM_CHUNK_DATA(chunk) ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
-#define GST_MEM_CHUNK_LINK(mem) ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
-
-/*******************************************************
- * area size
- * +-----------------------------------------+
- * chunk size
- * +------------+
- *
- * !next!data... !next!data.... !next!data...
- * ! ^ ! ^ !
- * +-------------+ +------------+ +---> NULL
- *
- */
-static gboolean
-populate (GstMemChunk * mem_chunk)
-{
- guint8 *area;
- gint i;
-
- if (mem_chunk->cleanup)
- return FALSE;
-
- area = (guint8 *) g_malloc (mem_chunk->area_size);
- g_print ("alloc %p\n", area);
-
- for (i = 0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
- GST_MEM_CHUNK_AREA (area + i) = (GstMemChunkElement *) area;
- gst_mem_chunk_free (mem_chunk, GST_MEM_CHUNK_DATA (area + i));
- }
-
- return TRUE;
-}
-
-
-GstMemChunk *
-gst_mem_chunk_new (gchar * name, gint atom_size, gulong area_size, gint type)
-{
- GstMemChunk *mem_chunk;
-
- g_return_val_if_fail (atom_size > 0, NULL);
- g_return_val_if_fail (area_size >= atom_size, NULL);
-
- mem_chunk = g_malloc (sizeof (GstMemChunk));
-
- mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
- area_size = (area_size / atom_size) * mem_chunk->chunk_size;
-
- mem_chunk->name = g_strdup (name);
- mem_chunk->free = NULL;
- mem_chunk->cnt = 0;
- mem_chunk->atom_size = atom_size;
- mem_chunk->area_size = area_size;
- mem_chunk->cleanup = FALSE;
-
- populate (mem_chunk);
-
- return mem_chunk;
-}
-
-static gboolean
-free_area (gpointer key, gpointer value, gpointer user_data)
-{
- g_print ("free %p\n", key);
- g_free (key);
-
- return TRUE;
-}
-
-void
-gst_mem_chunk_destroy (GstMemChunk * mem_chunk)
-{
- GHashTable *elements = g_hash_table_new (NULL, NULL);
- gpointer data;
-
- mem_chunk->cleanup = TRUE;
-
- data = gst_mem_chunk_alloc (mem_chunk);
- while (data) {
- GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
-
- g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL);
-
- data = gst_mem_chunk_alloc (mem_chunk);
- }
- g_hash_table_foreach_remove (elements, free_area, NULL);
-
- g_hash_table_destroy (elements);
- g_free (mem_chunk->name);
- g_free (mem_chunk);
-}
-
-gpointer
-gst_mem_chunk_alloc (GstMemChunk * mem_chunk)
-{
- GstMemChunkElement *chunk = NULL;
-
- g_return_val_if_fail (mem_chunk != NULL, NULL);
-
-again:
-#ifdef HAVE_I386
-__asm__ __volatile__ (" testl %%eax, %%eax \n\t" " jz 20f \n" "10: \t" " movl (%%eax), %%ebx \n\t" " movl %%edx, %%ecx \n\t" " incl %%ecx \n\t" CHUNK_LOCK "cmpxchg8b %1 \n\t" " jz 20f \n\t" " testl %%eax, %%eax \n\t" " jnz 10b \n" "20:\t":"=a" (chunk)
-: "m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt)
-: "ecx", "ebx");
-#else
- fprintf (stderr, "This only compiles correctly on i386. Sorry\n");
- abort ();
-#endif
-
- if (!chunk) {
- /*g_print ("extending\n"); */
- if (populate (mem_chunk))
- goto again;
- else
- return NULL;
- }
- return GST_MEM_CHUNK_DATA (chunk);
-}
-
-gpointer
-gst_mem_chunk_alloc0 (GstMemChunk * mem_chunk)
-{
- gpointer mem = gst_mem_chunk_alloc (mem_chunk);
-
- if (mem)
- memset (mem, 0, mem_chunk->atom_size);
-
- return mem;
-}
-
-void
-gst_mem_chunk_free (GstMemChunk * mem_chunk, gpointer mem)
-{
- GstMemChunkElement *chunk;
-
- g_return_if_fail (mem_chunk != NULL);
- g_return_if_fail (mem != NULL);
-
- chunk = GST_MEM_CHUNK_LINK (mem);
-
-#ifdef HAVE_I386
- __asm__ __volatile__ ("1: \t"
- " movl %2, (%1) \n"
- CHUNK_LOCK "cmpxchg %1, %0 \n\t"
- " jnz 1b \n\t"::
- "m" (*mem_chunk), "r" (chunk), "a" (mem_chunk->free));
-#else
- fprintf (stderr, "This only compiles correctly on i386. Sorry\n");
- abort ();
-#endif
-}
+++ /dev/null
-
-#include <gst/gst.h>
-
-typedef struct _GstMemChunk GstMemChunk;
-typedef struct _GstMemChunkElement GstMemChunkElement;
-
-struct _GstMemChunkElement
-{
- GstMemChunkElement *link; /* next cell in the lifo */
- GstMemChunkElement *area;
-};
-
-struct _GstMemChunk
-{
- volatile GstMemChunkElement *free; /* the first free element */
- volatile gulong cnt; /* used to avoid ABA problem */
-
- gchar *name;
- gulong area_size;
- gulong chunk_size;
- gulong atom_size;
- gboolean cleanup;
-};
-
-GstMemChunk* gst_mem_chunk_new (gchar *name,
- gint atom_size,
- gulong area_size,
- gint type);
-
-void gst_mem_chunk_destroy (GstMemChunk *mem_chunk);
-
-gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
-void gst_mem_chunk_free (GstMemChunk *mem_chunk,
- gpointer mem);
+++ /dev/null
-#include <string.h> /* strerror */
-#include <stdlib.h> /* strerror */
-#include <gst/gst.h>
-#include "gstmemchunk.h"
-
-#define MAX_THREADS 100
-
-static GstMemChunk *_chunks;
-
-static gint num_allocs;
-static gint num_threads;
-
-static gpointer
-alloc_chunk (void)
-{
- gpointer ret;
-
- ret = gst_mem_chunk_alloc (_chunks);
-
- return ret;
-}
-
-static void
-free_chunk (gpointer chunk)
-{
- gst_mem_chunk_free (_chunks, chunk);
-}
-
-
-void *
-run_test (void *threadid)
-{
- gint i;
- gpointer chunk;
-
- g_usleep (G_USEC_PER_SEC);
-
- for (i = 0; i < num_allocs; i++) {
- chunk = alloc_chunk ();
- free_chunk (chunk);
- }
-
- g_thread_exit (NULL);
- return NULL;
-}
-
-
-gint
-main (gint argc, gchar * argv[])
-{
- GThread *threads[MAX_THREADS];
- GError *error;
- int t;
-
- gst_init (&argc, &argv);
-
- if (argc != 3) {
- g_print ("usage: %s <num_threads> <num_allocs>\n", argv[0]);
- exit (-1);
- }
-
- num_threads = atoi (argv[1]);
- num_allocs = atoi (argv[2]);
-
- _chunks = gst_mem_chunk_new ("test", 32, 32 * 16, G_ALLOC_AND_FREE);
-
- for (t = 0; t < num_threads; t++) {
- error = NULL;
- threads[t] = g_thread_create (run_test, GINT_TO_POINTER (t), TRUE, &error);
- if (error) {
- printf ("ERROR: g_thread_create() %s\n", error->message);
- exit (-1);
- }
- }
- printf ("main(): Created %d threads.\n", t);
-
- for (t = 0; t < num_threads; t++) {
- g_thread_join (threads[t]);
- }
- g_mem_chunk_info ();
-
- gst_mem_chunk_destroy (_chunks);
-
- return 0;
-}