-/*
- * mlt_pool.c -- memory pooling functionality
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
+/**
+ * \file mlt_pool.c
+ * \brief memory pooling functionality
+ * \see mlt_pool_s
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * \author Charles Yates <charles.yates@pandora.be>
*
- * This program is distributed in the hope that it will be useful,
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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 General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Lesser 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 "mlt_properties.h"
#include "mlt_deque.h"
#include <stdlib.h>
-#include <malloc.h>
#include <string.h>
#include <pthread.h>
-/** Singleton repositories
-*/
+// Not nice - memalign is defined here apparently?
+#ifdef linux
+#include <malloc.h>
+#endif
+
+/** global singleton for tracking pools */
static mlt_properties pools = NULL;
-/** Private pooling structure.
-*/
+/** \brief Pool (memory) class
+ */
typedef struct mlt_pool_s
{
- pthread_mutex_t lock;
- mlt_deque stack;
- int size;
- int count;
+ pthread_mutex_t lock; ///< lock to prevent race conditions
+ mlt_deque stack; ///< a stack of addresses to memory blocks
+ int size; ///< the size of the memory block as a power of 2
+ int count; ///< the number of blocks in the pool
}
*mlt_pool;
+/** \brief private to mlt_pool_s, for tracking items to release
+ */
+
typedef struct mlt_release_s
{
mlt_pool pool;
*mlt_release;
/** Create a pool.
-*/
+ *
+ * \private \memberof mlt_pool_s
+ * \param size the size of the memory blocks to hold as some power of two
+ * \return a new pool object
+ */
static mlt_pool pool_init( int size )
{
}
/** Get an item from the pool.
-*/
+ *
+ * \private \memberof mlt_pool_s
+ * \param this a pool
+ * \return an opaque pointer
+ */
static void *pool_fetch( mlt_pool this )
{
else
{
// We need to generate a release item
+#ifdef linux
mlt_release release = memalign( 16, this->size );
+#else
+ mlt_release release = malloc( this->size );
+#endif
// Initialise it
if ( release != NULL )
{
+ // Increment the number of items allocated to this pool
+ this->count ++;
+
// Assign the pool
release->pool = this;
release->references = 1;
// Determine the ptr
- ptr = ( void * )release + sizeof( struct mlt_release_s );
+ ptr = ( char * )release + sizeof( struct mlt_release_s );
}
}
}
/** Return an item to the pool.
-*/
+ *
+ * \private \memberof mlt_pool_s
+ * \param ptr an opaque pointer
+ */
static void pool_return( void *ptr )
{
if ( ptr != NULL )
{
// Get the release pointer
- mlt_release that = ptr - sizeof( struct mlt_release_s );
+ mlt_release that = ( void * )(( char * )ptr - sizeof( struct mlt_release_s ));
// Get the pool
mlt_pool this = that->pool;
if ( ptr != NULL )
{
// Free the release itself
- free( ptr - sizeof( struct mlt_release_s ) );
+ free( ( char * )ptr - sizeof( struct mlt_release_s ) );
}
}
/** Destroy a pool.
-*/
+ *
+ * \private \memberof mlt_pool_s
+ * \param this a pool
+ */
static void pool_close( mlt_pool this )
{
while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
{
// We'll free this item now
- free( release - sizeof( struct mlt_release_s ) );
+ free( ( char * )release - sizeof( struct mlt_release_s ) );
}
// We can now close the stack
}
}
-/** Initialise the pool.
-*/
+/** Initialise the global pool.
+ *
+ * \public \memberof mlt_pool_s
+ */
void mlt_pool_init( )
{
}
/** Allocate size bytes from the pool.
-*/
+ *
+ * \public \memberof mlt_pool_s
+ * \param size the number of bytes
+ */
void *mlt_pool_alloc( int size )
{
}
/** Allocate size bytes from the pool.
-*/
+ *
+ * \public \memberof mlt_pool_s
+ * \param ptr an opaque pointer - can be in the pool or a new block to allocate
+ * \param size the number of bytes
+ */
void *mlt_pool_realloc( void *ptr, int size )
{
if ( ptr != NULL )
{
// Get the release pointer
- mlt_release that = ptr - sizeof( struct mlt_release_s );
+ mlt_release that = ( void * )(( char * )ptr - sizeof( struct mlt_release_s ));
// If the current pool this ptr belongs to is big enough
if ( size > that->pool->size - sizeof( struct mlt_release_s ) )
return result;
}
+/** Purge unused items in the pool.
+ *
+ * A form of garbage collection.
+ * \public \memberof mlt_pool_s
+ */
+
+void mlt_pool_purge( )
+{
+ int i = 0;
+
+ // For each pool
+ for ( i = 0; i < mlt_properties_count( pools ); i ++ )
+ {
+ // Get the pool
+ mlt_pool this = mlt_properties_get_data_at( pools, i, NULL );
+
+ // Pointer to unused memory
+ void *release = NULL;
+
+ // Lock the pool
+ pthread_mutex_lock( &this->lock );
+
+ // We'll free all unused items now
+ while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
+ free( ( char * )release - sizeof( struct mlt_release_s ) );
+
+ // Unlock the pool
+ pthread_mutex_unlock( &this->lock );
+ }
+}
+
/** Release the allocated memory.
-*/
+ *
+ * \public \memberof mlt_pool_s
+ * \param release an opaque pointer of a block in the pool
+ */
void mlt_pool_release( void *release )
{
}
/** Close the pool.
-*/
+ *
+ * \public \memberof mlt_pool_s
+ */
void mlt_pool_close( )
{
+#ifdef _MLT_POOL_CHECKS_
+ // Stats dump on close
+ int i = 0;
+ for ( i = 0; i < mlt_properties_count( pools ); i ++ )
+ {
+ mlt_pool pool = mlt_properties_get_data_at( pools, i, NULL );
+ if ( pool->count )
+ mlt_log( NULL, MLT_LOG_DEBUG, "%s: size %d allocated %d returned %d %c\n", __FUNCTION__,
+ pool->size, pool->count, mlt_deque_count( pool->stack ),
+ pool->count != mlt_deque_count( pool->stack ) ? '*' : ' ' );
+ }
+#endif
+
// Close the properties
mlt_properties_close( pools );
}