2 * mlt_pool.c -- memory pooling functionality
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "mlt_properties.h"
22 #include "mlt_deque.h"
29 /** Singleton repositories
32 static mlt_properties pools = NULL;
34 /** Private pooling structure.
37 typedef struct mlt_pool_s
46 typedef struct mlt_release_s
56 static mlt_pool pool_init( int size )
59 mlt_pool this = calloc( 1, sizeof( struct mlt_pool_s ) );
64 // Initialise the mutex
65 pthread_mutex_init( &this->lock, NULL );
68 this->stack = mlt_deque_init( );
78 /** Get an item from the pool.
81 static void *pool_fetch( mlt_pool this )
83 // We will generate a release object
90 pthread_mutex_lock( &this->lock );
92 // Check if the stack is empty
93 if ( mlt_deque_count( this->stack ) != 0 )
95 // Pop the top of the stack
96 ptr = mlt_deque_pop_back( this->stack );
98 // Assign the reference
99 ( ( mlt_release )ptr )->references = 1;
103 // We need to generate a release item
104 mlt_release release = memalign( 16, this->size );
107 if ( release != NULL )
109 // Increment the number of items allocated to this pool
113 release->pool = this;
115 // Assign the reference
116 release->references = 1;
119 ptr = ( void * )release + sizeof( struct mlt_release_s );
124 pthread_mutex_unlock( &this->lock );
127 // Return the generated release object
131 /** Return an item to the pool.
134 static void pool_return( void *ptr )
139 // Get the release pointer
140 mlt_release that = ptr - sizeof( struct mlt_release_s );
143 mlt_pool this = that->pool;
148 pthread_mutex_lock( &this->lock );
150 // Push the that back back on to the stack
151 mlt_deque_push_back( this->stack, ptr );
154 pthread_mutex_unlock( &this->lock );
156 // Ensure that we don't clean up
161 // Tidy up - this will only occur if the returned item is incorrect
164 // Free the release itself
165 free( ptr - sizeof( struct mlt_release_s ) );
172 static void pool_close( mlt_pool this )
176 // We need to free up all items in the pool
177 void *release = NULL;
179 // Iterate through the stack until depleted
180 while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
182 // We'll free this item now
183 free( release - sizeof( struct mlt_release_s ) );
186 // We can now close the stack
187 mlt_deque_close( this->stack );
190 pthread_mutex_destroy( &this->lock );
197 /** Initialise the pool.
200 void mlt_pool_init( )
202 // Loop variable used to create the pools
206 pools = mlt_properties_new( );
209 for ( i = 8; i < 31; i ++ )
211 // Each properties item needs a name
215 mlt_pool pool = pool_init( 1 << i );
218 sprintf( name, "%d", i );
220 // Register with properties
221 mlt_properties_set_data( pools, name, pool, 0, ( mlt_destructor )pool_close, NULL );
225 /** Allocate size bytes from the pool.
228 void *mlt_pool_alloc( int size )
230 // This will be used to obtain the pool to use
231 mlt_pool pool = NULL;
233 // Determines the index of the pool to use
236 // Minimum size pooled is 256 bytes
237 size = size + sizeof( mlt_release );
238 while ( ( 1 << index ) < size )
241 // Now get the pool at the index
242 pool = mlt_properties_get_data_at( pools, index - 8, NULL );
244 // Now get the real item
245 return pool_fetch( pool );
248 /** Allocate size bytes from the pool.
251 void *mlt_pool_realloc( void *ptr, int size )
256 // Check if we actually have an address
259 // Get the release pointer
260 mlt_release that = ptr - sizeof( struct mlt_release_s );
262 // If the current pool this ptr belongs to is big enough
263 if ( size > that->pool->size - sizeof( struct mlt_release_s ) )
266 result = mlt_pool_alloc( size );
269 memcpy( result, ptr, that->pool->size - sizeof( struct mlt_release_s ) );
272 mlt_pool_release( ptr );
283 result = mlt_pool_alloc( size );
289 /** Release the allocated memory.
292 void mlt_pool_release( void *release )
294 // Return to the pool
295 pool_return( release );
301 void mlt_pool_close( )
303 #ifdef _MLT_POOL_CHECKS_
304 // Stats dump on close
306 fprintf( stderr, "Usage:\n\n" );
307 for ( i = 0; i < mlt_properties_count( pools ); i ++ )
309 mlt_pool pool = mlt_properties_get_data_at( pools, i, NULL );
311 fprintf( stderr, "%d: allocated %d returned %d %c\n", pool->size, pool->count, mlt_deque_count( pool->stack ),
312 pool->count != mlt_deque_count( pool->stack ) ? '*' : ' ' );
316 // Close the properties
317 mlt_properties_close( pools );