1 Add option GST_BUFFER_WHERE (off by default) to track the file:line info where each buffer is created. This is use...

Original commit message from CVS:
1 Add option GST_BUFFER_WHERE (off by default) to track the file:line
info where each buffer is created.  This is useful for tracking
buffer memory leaks.

2 Removed gst_buffer_ref_by_count.

3 Merged the GstBufferCopyFunc fix from HEAD.
This commit is contained in:
Joshua N. Pritikin 2001-09-23 01:47:10 +00:00
parent c1051d5087
commit 4f81b9a5da
3 changed files with 157 additions and 60 deletions

View file

@ -32,6 +32,13 @@ GType _gst_buffer_type;
static GMemChunk *_gst_buffer_chunk;
static GMutex *_gst_buffer_chunk_lock;
#ifdef GST_BUFFER_WHERE
static GSList *_debug_live = 0;
# define GST_BUFFERS_COUNT (g_slist_length(_debug_live))
#else
# define GST_BUFFERS_COUNT 1
#endif
void
_gst_buffer_initialize (void)
{
@ -67,12 +74,15 @@ _gst_buffer_initialize (void)
* Returns: new buffer
*/
GstBuffer*
gst_buffer_new (void)
gst_buffer_new_loc (GST_WHERE)
{
GstBuffer *buffer;
g_mutex_lock (_gst_buffer_chunk_lock);
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
#ifdef GST_BUFFER_WHERE
_debug_live = g_slist_prepend (_debug_live, buffer);
#endif
g_mutex_unlock (_gst_buffer_chunk_lock);
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer);
@ -96,6 +106,11 @@ gst_buffer_new (void)
buffer->free = NULL;
buffer->copy = NULL;
#ifdef GST_BUFFER_WHERE
buffer->file = where_file;
buffer->line = where_line;
#endif
return buffer;
}
@ -108,18 +123,21 @@ gst_buffer_new (void)
* Returns: new buffer
*/
GstBuffer*
gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size)
{
GstBuffer *buffer;
g_return_val_if_fail (pool != NULL, NULL);
g_return_val_if_fail (pool->buffer_new != NULL, NULL);
buffer = pool->buffer_new (pool, location, size, pool->user_data);
buffer = pool->buffer_new (pool, offset, size, pool->user_data);
buffer->pool = pool;
buffer->free = pool->buffer_free;
buffer->copy = pool->buffer_copy;
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p from pool %p (size %x, offset %x)",
buffer, pool, size, offset);
return buffer;
}
@ -134,9 +152,10 @@ gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
* Returns: new buffer
*/
GstBuffer*
gst_buffer_create_sub (GstBuffer *parent,
guint32 offset,
guint32 size)
gst_buffer_create_sub_loc (GST_WHERE_
GstBuffer *parent,
guint32 offset,
guint32 size)
{
GstBuffer *buffer;
@ -146,6 +165,9 @@ gst_buffer_create_sub (GstBuffer *parent,
g_mutex_lock (_gst_buffer_chunk_lock);
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
#ifdef GST_BUFFER_WHERE
_debug_live = g_slist_prepend (_debug_live, buffer);
#endif
g_mutex_unlock (_gst_buffer_chunk_lock);
GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p (size %u, offset %u)",
buffer, parent, size, offset);
@ -184,7 +206,12 @@ gst_buffer_create_sub (GstBuffer *parent,
gst_buffer_ref (parent);
buffer->pool = NULL;
// return the new subbuffer
#ifdef GST_BUFFER_WHERE
buffer->file = where_file;
buffer->line = where_line;
#endif
return buffer;
}
@ -201,8 +228,9 @@ gst_buffer_create_sub (GstBuffer *parent,
* Returns: new buffer
*/
GstBuffer*
gst_buffer_append (GstBuffer *buffer,
GstBuffer *append)
gst_buffer_append_loc (GST_WHERE_
GstBuffer *buffer,
GstBuffer *append)
{
guint size;
GstBuffer *newbuf;
@ -226,7 +254,7 @@ gst_buffer_append (GstBuffer *buffer,
}
// the buffer is used, create a new one
else {
newbuf = gst_buffer_new ();
newbuf = gst_buffer_new_loc (GST_WHERE_VARS);
newbuf->size = buffer->size+append->size;
newbuf->data = g_malloc (newbuf->size);
memcpy (newbuf->data, buffer->data, buffer->size);
@ -250,7 +278,10 @@ gst_buffer_destroy (GstBuffer *buffer)
g_return_if_fail (buffer != NULL);
GST_INFO (GST_CAT_BUFFER,"freeing %sbuffer %p", (buffer->parent?"sub":""),buffer);
GST_INFO (GST_CAT_BUFFER, "freeing %sbuffer %p (%ld buffers remain)",
(buffer->parent?"sub":""),
buffer,
GST_BUFFERS_COUNT - 1);
// free the data only if there is some, DONTFREE isn't set, and not sub
if (GST_BUFFER_DATA (buffer) &&
@ -271,12 +302,33 @@ gst_buffer_destroy (GstBuffer *buffer)
g_mutex_free (buffer->lock);
//g_print("freed mutex\n");
#ifdef GST_DEBUG_ENABLED
// make it hard to reuse by mistake
memset (buffer, ~0, sizeof (GstBuffer));
#endif
// remove it entirely from memory
g_mutex_lock (_gst_buffer_chunk_lock);
g_mem_chunk_free (_gst_buffer_chunk,buffer);
#ifdef GST_BUFFER_WHERE
_debug_live = g_slist_delete_link (_debug_live,
g_slist_find (_debug_live, buffer));
#endif
g_mutex_unlock (_gst_buffer_chunk_lock);
}
#ifdef GST_BUFFER_WHERE
void gst_buffer_print_live ()
{
GSList *elem;
for (elem = _debug_live; elem; elem = elem->next) {
GstBuffer *buf = elem->data;
g_print ("buffer %p created %s:%d\n", buf, buf->file, buf->line);
}
}
#endif
/**
* gst_buffer_ref:
* @buffer: the GstBuffer to reference
@ -288,7 +340,7 @@ gst_buffer_ref (GstBuffer *buffer)
{
g_return_if_fail (buffer != NULL);
GST_DEBUG (0,"referencing buffer %p\n", buffer);
GST_INFO (GST_CAT_BUFFER, "ref buffer %p\n", buffer);
#ifdef HAVE_ATOMIC_H
//g_return_if_fail(atomic_read(&(buffer->refcount)) > 0);
@ -301,30 +353,6 @@ gst_buffer_ref (GstBuffer *buffer)
#endif
}
/**
* gst_buffer_ref_by_count:
* @buffer: the GstBuffer to reference
* @count: a number
*
* Increment the refcount of this buffer by the given number.
*/
void
gst_buffer_ref_by_count (GstBuffer *buffer, int count)
{
g_return_if_fail (buffer != NULL);
g_return_if_fail (count > 0);
#ifdef HAVE_ATOMIC_H
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
atomic_add (count, &(buffer->refcount));
#else
g_return_if_fail (buffer->refcount > 0);
GST_BUFFER_LOCK (buffer);
buffer->refcount += count;
GST_BUFFER_UNLOCK (buffer);
#endif
}
/**
* gst_buffer_unref:
* @buffer: the GstBuffer to unref
@ -339,7 +367,7 @@ gst_buffer_unref (GstBuffer *buffer)
g_return_if_fail (buffer != NULL);
GST_DEBUG (0,"unreferencing buffer %p\n", buffer);
GST_INFO (GST_CAT_BUFFER, "unref buffer %p\n", buffer);
#ifdef HAVE_ATOMIC_H
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
@ -367,17 +395,17 @@ gst_buffer_unref (GstBuffer *buffer)
* Returns: new buffer
*/
GstBuffer *
gst_buffer_copy (GstBuffer *buffer)
gst_buffer_copy_loc (GST_WHERE_ GstBuffer *buffer)
{
GstBuffer *newbuf;
// allocate a new buffer
newbuf = gst_buffer_new();
// if a copy function exists, use it, else copy the bytes
if (buffer->copy != NULL) {
(buffer->copy)(buffer,newbuf);
newbuf = (buffer->copy)(buffer);
} else {
// allocate a new buffer
newbuf = gst_buffer_new();
// copy the absolute size
newbuf->size = buffer->size;
// allocate space for the copy
@ -436,7 +464,8 @@ gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
*/
// FIXME need to think about CoW and such...
GstBuffer *
gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
gst_buffer_span_loc (GST_WHERE_
GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
{
GstBuffer *newbuf;
@ -453,12 +482,13 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
// ((buf1->data + buf1->size) == buf2->data)) {
if (gst_buffer_is_span_fast(buf1,buf2)) {
// we simply create a subbuffer of the common parent
newbuf = gst_buffer_create_sub(buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
newbuf = gst_buffer_create_sub_loc(GST_WHERE_VARS_
buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
}
else {
g_print ("slow path taken in buffer_span\n");
// otherwise we simply have to brute-force copy the buffers
newbuf = gst_buffer_new();
newbuf = gst_buffer_new_loc (GST_WHERE_VARS);
// put in new size
newbuf->size = len;
@ -496,8 +526,10 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
* Returns: new buffer that's the concatenation of the source buffers
*/
GstBuffer *
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
gst_buffer_merge_loc (GST_WHERE_
GstBuffer *buf1, GstBuffer *buf2)
{
// we're just a specific case of the more general gst_buffer_span()
return gst_buffer_span(buf1, 0, buf2, buf1->size + buf2->size);
return gst_buffer_span_loc (GST_WHERE_VARS_
buf1, 0, buf2, buf1->size + buf2->size);
}

View file

@ -24,6 +24,13 @@
#ifndef __GST_BUFFER_H__
#define __GST_BUFFER_H__
//
// Define this to add file:line info to each GstBuffer showing
// the location in the source code where the buffer was created.
//
// #define GST_BUFFER_WHERE
//
#include <gst/gstdata.h>
#include <gst/gstobject.h>
@ -89,8 +96,8 @@ typedef enum {
typedef struct _GstBuffer GstBuffer;
typedef void (*GstBufferFreeFunc) (GstBuffer *buf);
typedef void (*GstBufferCopyFunc) (GstBuffer *srcbuf,GstBuffer *dstbuf);
typedef void (*GstBufferFreeFunc) (GstBuffer *buf);
typedef GstBuffer *(*GstBufferCopyFunc) (GstBuffer *srcbuf);
#include <gst/gstbufferpool.h>
@ -119,9 +126,13 @@ struct _GstBuffer {
guint32 maxsize;
guint32 offset;
#ifdef GST_BUFFER_WHERE
const gchar *file;
gint line;
#endif
/* timestamp */
gint64 timestamp;
/* max age */
gint64 maxage;
/* subbuffer support, who's my parent? */
@ -136,30 +147,76 @@ struct _GstBuffer {
GstBufferCopyFunc copy; // copy the data from one buffer to another
};
#ifdef GST_BUFFER_WHERE
# define GST_WHERE const gchar *where_file, gint where_line
# define GST_WHERE_ GST_WHERE,
# define GST_WHERE_VARS where_file, where_line
# define GST_WHERE_VARS_ where_file, where_line,
# define gst_buffer_new() \
gst_buffer_new_loc(__FILE__, __LINE__)
# define gst_buffer_create_sub(parent, offset, size) \
gst_buffer_create_sub_loc(__FILE__, __LINE__, parent, offset, size)
# define gst_buffer_copy(buffer) \
gst_buffer_copy_loc(__FILE__, __LINE__, buffer)
# define gst_buffer_merge(buf1, buf2) \
gst_buffer_merge_loc(__FILE__, __LINE__, buf1, buf2)
# define gst_buffer_span(buf1, offset, buf2, len) \
gst_buffer_span_loc(__FILE__, __LINE__, buf1, offset, buf2, len)
# define gst_buffer_append(buf, buf2) \
gst_buffer_append_loc(__FILE__, __LINE__, buf, buf2)
#else /* GST_BUFFER_WHERE */
# define GST_WHERE
# define GST_WHERE_
# define GST_WHERE_VARS
# define GST_WHERE_VARS_
# define gst_buffer_new() \
gst_buffer_new_loc()
# define gst_buffer_create_sub(parent, offset, size) \
gst_buffer_create_sub_loc(parent, offset, size)
# define gst_buffer_copy(buffer) \
gst_buffer_copy_loc(buffer)
# define gst_buffer_merge(buf1, buf2) \
gst_buffer_merge_loc(buf1, buf2)
# define gst_buffer_span(buf1, offset, buf2, len) \
gst_buffer_span_loc(buf1, offset, buf2, len)
# define gst_buffer_append(buf, buf2) \
gst_buffer_append_loc(buf, buf2)
#endif /* GST_BUFFER_WHERE */
/* initialisation */
void _gst_buffer_initialize (void);
/* creating a new buffer from scratch */
GstBuffer* gst_buffer_new (void);
GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size);
GstBuffer* gst_buffer_new_loc (GST_WHERE);
GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size);
/* creating a subbuffer */
GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint32 offset, guint32 size);
GstBuffer* gst_buffer_create_sub_loc (GST_WHERE_
GstBuffer *parent, guint32 offset, guint32 size);
/* refcounting */
void gst_buffer_ref (GstBuffer *buffer);
void gst_buffer_ref_by_count (GstBuffer *buffer, int count);
void gst_buffer_unref (GstBuffer *buffer);
/* destroying the buffer */
void gst_buffer_destroy (GstBuffer *buffer);
/* copy buffer */
GstBuffer* gst_buffer_copy (GstBuffer *buffer);
GstBuffer* gst_buffer_copy_loc (GST_WHERE_
GstBuffer *buffer);
/* merge, span, or append two buffers, intelligently */
GstBuffer* gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2);
GstBuffer* gst_buffer_span (GstBuffer *buf1,guint32 offset,GstBuffer *buf2,guint32 len);
GstBuffer* gst_buffer_append (GstBuffer *buf, GstBuffer *buf2);
GstBuffer* gst_buffer_merge_loc (GST_WHERE_
GstBuffer *buf1, GstBuffer *buf2);
GstBuffer* gst_buffer_span_loc (GST_WHERE_
GstBuffer *buf1,guint32 offset,GstBuffer *buf2,guint32 len);
GstBuffer* gst_buffer_append_loc (GST_WHERE_
GstBuffer *buf, GstBuffer *buf2);
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);

View file

@ -194,7 +194,8 @@ gst_buffer_pool_set_buffer_free_function (GstBufferPool *pool,
* @destroy: the copy function
*
* Sets the function that will be called when a buffer is copied.
* You can use the default GstBuffer implementation (gst_buffer_copy) if you like.
*
* You may use the default GstBuffer implementation (gst_buffer_copy).
*/
void
gst_buffer_pool_set_buffer_copy_function (GstBufferPool *pool,
@ -273,6 +274,13 @@ gst_buffer_pool_destroy (GstBufferPool *pool)
g_free(pool);
}
//
// This is so we don't get messed up by GST_BUFFER_WHERE.
//
static GstBuffer *
_pool_gst_buffer_copy (GstBuffer *buffer)
{ return gst_buffer_copy (buffer); }
/**
* gst_buffer_pool_get_default:
* @buffer_size: the number of bytes this buffer will store
@ -313,7 +321,7 @@ gst_buffer_pool_get_default (guint buffer_size, guint pool_size)
pool = gst_buffer_pool_new();
gst_buffer_pool_set_buffer_new_function (pool, gst_buffer_pool_default_buffer_new);
gst_buffer_pool_set_buffer_free_function (pool, gst_buffer_pool_default_buffer_free);
gst_buffer_pool_set_buffer_copy_function (pool, gst_buffer_copy);
gst_buffer_pool_set_buffer_copy_function (pool, _pool_gst_buffer_copy);
gst_buffer_pool_set_destroy_hook (pool, gst_buffer_pool_default_destroy_hook);
def = g_new0 (GstBufferPoolDefault, 1);