3 * \brief memory pooling functionality
5 * Copyright (C) 2003-2008 Ushodaya Enterprises Limited
6 * \author Charles Yates <charles.yates@pandora.be>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "mlt_properties.h"
24 #include "mlt_deque.h"
30 // Not nice - memalign is defined here apparently?
35 /** Singleton repositories
38 static mlt_properties pools = NULL;
40 /** \brief Pool (memory) class
43 typedef struct mlt_pool_s
52 /** \brief private to mlt_pool_s, for tracking items to release
55 typedef struct mlt_release_s
65 static mlt_pool pool_init( int size )
68 mlt_pool this = calloc( 1, sizeof( struct mlt_pool_s ) );
73 // Initialise the mutex
74 pthread_mutex_init( &this->lock, NULL );
77 this->stack = mlt_deque_init( );
87 /** Get an item from the pool.
90 static void *pool_fetch( mlt_pool this )
92 // We will generate a release object
99 pthread_mutex_lock( &this->lock );
101 // Check if the stack is empty
102 if ( mlt_deque_count( this->stack ) != 0 )
104 // Pop the top of the stack
105 ptr = mlt_deque_pop_back( this->stack );
107 // Assign the reference
108 ( ( mlt_release )ptr )->references = 1;
112 // We need to generate a release item
114 mlt_release release = memalign( 16, this->size );
116 mlt_release release = malloc( this->size );
120 if ( release != NULL )
122 // Increment the number of items allocated to this pool
126 release->pool = this;
128 // Assign the reference
129 release->references = 1;
132 ptr = ( void * )release + sizeof( struct mlt_release_s );
137 pthread_mutex_unlock( &this->lock );
140 // Return the generated release object
144 /** Return an item to the pool.
147 static void pool_return( void *ptr )
152 // Get the release pointer
153 mlt_release that = ptr - sizeof( struct mlt_release_s );
156 mlt_pool this = that->pool;
161 pthread_mutex_lock( &this->lock );
163 // Push the that back back on to the stack
164 mlt_deque_push_back( this->stack, ptr );
167 pthread_mutex_unlock( &this->lock );
169 // Ensure that we don't clean up
174 // Tidy up - this will only occur if the returned item is incorrect
177 // Free the release itself
178 free( ptr - sizeof( struct mlt_release_s ) );
185 static void pool_close( mlt_pool this )
189 // We need to free up all items in the pool
190 void *release = NULL;
192 // Iterate through the stack until depleted
193 while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
195 // We'll free this item now
196 free( release - sizeof( struct mlt_release_s ) );
199 // We can now close the stack
200 mlt_deque_close( this->stack );
203 pthread_mutex_destroy( &this->lock );
210 /** Initialise the pool.
213 void mlt_pool_init( )
215 // Loop variable used to create the pools
219 pools = mlt_properties_new( );
222 for ( i = 8; i < 31; i ++ )
224 // Each properties item needs a name
228 mlt_pool pool = pool_init( 1 << i );
231 sprintf( name, "%d", i );
233 // Register with properties
234 mlt_properties_set_data( pools, name, pool, 0, ( mlt_destructor )pool_close, NULL );
238 /** Allocate size bytes from the pool.
241 void *mlt_pool_alloc( int size )
243 // This will be used to obtain the pool to use
244 mlt_pool pool = NULL;
246 // Determines the index of the pool to use
249 // Minimum size pooled is 256 bytes
250 size = size + sizeof( mlt_release );
251 while ( ( 1 << index ) < size )
254 // Now get the pool at the index
255 pool = mlt_properties_get_data_at( pools, index - 8, NULL );
257 // Now get the real item
258 return pool_fetch( pool );
261 /** Allocate size bytes from the pool.
264 void *mlt_pool_realloc( void *ptr, int size )
269 // Check if we actually have an address
272 // Get the release pointer
273 mlt_release that = ptr - sizeof( struct mlt_release_s );
275 // If the current pool this ptr belongs to is big enough
276 if ( size > that->pool->size - sizeof( struct mlt_release_s ) )
279 result = mlt_pool_alloc( size );
282 memcpy( result, ptr, that->pool->size - sizeof( struct mlt_release_s ) );
285 mlt_pool_release( ptr );
296 result = mlt_pool_alloc( size );
302 /** Purge unused items in the pool.
305 void mlt_pool_purge( )
310 for ( i = 0; i < mlt_properties_count( pools ); i ++ )
313 mlt_pool this = mlt_properties_get_data_at( pools, i, NULL );
315 // Pointer to unused memory
316 void *release = NULL;
319 pthread_mutex_lock( &this->lock );
321 // We'll free all unused items now
322 while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
323 free( release - sizeof( struct mlt_release_s ) );
326 pthread_mutex_unlock( &this->lock );
330 /** Release the allocated memory.
333 void mlt_pool_release( void *release )
335 // Return to the pool
336 pool_return( release );
342 void mlt_pool_close( )
344 #ifdef _MLT_POOL_CHECKS_
345 // Stats dump on close
347 for ( i = 0; i < mlt_properties_count( pools ); i ++ )
349 mlt_pool pool = mlt_properties_get_data_at( pools, i, NULL );
351 mlt_log( NULL, MLT_LOG_DEBUG, "%s: size %d allocated %d returned %d %c\n", __FUNCTION__,
352 pool->size, pool->count, mlt_deque_count( pool->stack ),
353 pool->count != mlt_deque_count( pool->stack ) ? '*' : ' ' );
357 // Close the properties
358 mlt_properties_close( pools );