mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-07 06:52:41 +00:00
Remove memchunk benchmark stuff, this is taken over by GLib bug 118439.
Original commit message from CVS: 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.
This commit is contained in:
parent
b98900a0a0
commit
2f46ef713d
16 changed files with 108 additions and 616 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
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:
|
||||
|
|
|
@ -657,7 +657,6 @@ po/Makefile.in
|
|||
check/Makefile
|
||||
tests/Makefile
|
||||
tests/instantiate/Makefile
|
||||
tests/memchunk/Makefile
|
||||
tests/muxing/Makefile
|
||||
tests/seeking/Makefile
|
||||
tests/sched/Makefile
|
||||
|
|
|
@ -58,7 +58,7 @@ gst_controller_set_from_list
|
|||
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
|
||||
|
@ -86,7 +86,7 @@ gst_object_control_properties
|
|||
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>
|
||||
|
|
|
@ -886,6 +886,29 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
|
|||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -957,30 +980,22 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
|
|||
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);
|
||||
|
@ -1016,17 +1031,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3392,6 +3392,11 @@ _gst_value_initialize (void)
|
|||
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,
|
||||
|
|
|
@ -886,6 +886,29 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
|
|||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -957,30 +980,22 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
|
|||
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);
|
||||
|
@ -1016,17 +1031,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
* </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>
|
||||
|
@ -73,7 +73,7 @@
|
|||
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
GQuark controller_key;
|
||||
GQuark __gst_controller_key;
|
||||
|
||||
|
||||
/* imports from gst-interpolation.c */
|
||||
|
@ -94,7 +94,7 @@ on_object_controlled_property_changed (const GObject * object, GParamSpec * arg,
|
|||
|
||||
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)) {
|
||||
|
@ -420,7 +420,7 @@ gst_controller_new_valist (GObject * object, va_list var_args)
|
|||
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
|
||||
|
@ -432,7 +432,7 @@ gst_controller_new_valist (GObject * object, va_list var_args)
|
|||
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);
|
||||
|
@ -730,7 +730,7 @@ gst_controller_get_all (GstController * self, gchar * property_name)
|
|||
}
|
||||
|
||||
/**
|
||||
* gst_controller_sink_values:
|
||||
* gst_controller_sync_values:
|
||||
* @self: the controller that handles the values
|
||||
* @timestamp: the time that should be processed
|
||||
*
|
||||
|
@ -742,7 +742,7 @@ gst_controller_get_all (GstController * self, gchar * property_name)
|
|||
* Since: 0.9
|
||||
*/
|
||||
gboolean
|
||||
gst_controller_sink_values (GstController * self, GstClockTime timestamp)
|
||||
gst_controller_sync_values (GstController * self, GstClockTime timestamp)
|
||||
{
|
||||
GstControlledProperty *prop;
|
||||
GList *node;
|
||||
|
@ -752,7 +752,7 @@ gst_controller_sink_values (GstController * self, GstClockTime timestamp)
|
|||
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
|
||||
|
@ -954,7 +954,7 @@ _gst_controller_finalize (GObject * object)
|
|||
}
|
||||
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);
|
||||
|
@ -978,7 +978,7 @@ _gst_controller_class_init (GstControllerClass * klass)
|
|||
|
||||
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
|
||||
|
|
|
@ -225,7 +225,7 @@ const GList *gst_controller_get_all (GstController * self,
|
|||
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,
|
||||
|
@ -245,7 +245,7 @@ gboolean gst_object_uncontrol_properties (GObject * object, ...);
|
|||
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);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#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:
|
||||
|
@ -88,7 +88,7 @@ gst_object_uncontrol_properties (GObject * object, ...)
|
|||
|
||||
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);
|
||||
|
@ -110,7 +110,7 @@ gst_object_get_controller (GObject * 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,33 +131,33 @@ gst_object_set_controller (GObject * object, GstController * controller)
|
|||
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);
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ gst_object_get_value_arrays (GObject * object, GstClockTime timestamp,
|
|||
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);
|
||||
|
@ -220,7 +220,7 @@ gst_object_get_value_array (GObject * object, GstClockTime timestamp,
|
|||
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);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
SUBDIRS = instantiate memchunk muxing sched threadstate seeking
|
||||
SUBDIRS = instantiate muxing sched threadstate seeking
|
||||
|
||||
if GST_DISABLE_TRACE
|
||||
LAT =
|
||||
|
@ -15,4 +15,4 @@ LIBS = $(GST_OBJ_LIBS) \
|
|||
$(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
|
||||
|
|
5
tests/memchunk/.gitignore
vendored
5
tests/memchunk/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
|||
gmemchunktest
|
||||
gstmemchunktest
|
||||
*.bb
|
||||
*.bbg
|
||||
*.da
|
|
@ -1,7 +0,0 @@
|
|||
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)
|
|
@ -1,252 +0,0 @@
|
|||
/* 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;
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
#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
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
#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);
|
|
@ -1,85 +0,0 @@
|
|||
#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;
|
||||
}
|
Loading…
Reference in a new issue