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 library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "mlt_properties.h"
22 #include "mlt_deque.h"
28 // Not nice - memalign is defined here apparently?
33 /** Singleton repositories
36 static mlt_properties pools
= NULL
;
38 /** Private pooling structure.
41 typedef struct mlt_pool_s
50 typedef struct mlt_release_s
60 static mlt_pool
pool_init( int size
)
63 mlt_pool
this = calloc( 1, sizeof( struct mlt_pool_s
) );
68 // Initialise the mutex
69 pthread_mutex_init( &this->lock
, NULL
);
72 this->stack
= mlt_deque_init( );
82 /** Get an item from the pool.
85 static void *pool_fetch( mlt_pool
this )
87 // We will generate a release object
94 pthread_mutex_lock( &this->lock
);
96 // Check if the stack is empty
97 if ( mlt_deque_count( this->stack
) != 0 )
99 // Pop the top of the stack
100 ptr
= mlt_deque_pop_back( this->stack
);
102 // Assign the reference
103 ( ( mlt_release
)ptr
)->references
= 1;
107 // We need to generate a release item
109 mlt_release release
= memalign( 16, this->size
);
111 mlt_release release
= malloc( this->size
);
115 if ( release
!= NULL
)
117 // Increment the number of items allocated to this pool
121 release
->pool
= this;
123 // Assign the reference
124 release
->references
= 1;
127 ptr
= ( void * )release
+ sizeof( struct mlt_release_s
);
132 pthread_mutex_unlock( &this->lock
);
135 // Return the generated release object
139 /** Return an item to the pool.
142 static void pool_return( void *ptr
)
147 // Get the release pointer
148 mlt_release that
= ptr
- sizeof( struct mlt_release_s
);
151 mlt_pool
this = that
->pool
;
156 pthread_mutex_lock( &this->lock
);
158 // Push the that back back on to the stack
159 mlt_deque_push_back( this->stack
, ptr
);
162 pthread_mutex_unlock( &this->lock
);
164 // Ensure that we don't clean up
169 // Tidy up - this will only occur if the returned item is incorrect
172 // Free the release itself
173 free( ptr
- sizeof( struct mlt_release_s
) );
180 static void pool_close( mlt_pool
this )
184 // We need to free up all items in the pool
185 void *release
= NULL
;
187 // Iterate through the stack until depleted
188 while ( ( release
= mlt_deque_pop_back( this->stack
) ) != NULL
)
190 // We'll free this item now
191 free( release
- sizeof( struct mlt_release_s
) );
194 // We can now close the stack
195 mlt_deque_close( this->stack
);
198 pthread_mutex_destroy( &this->lock
);
205 /** Initialise the pool.
208 void mlt_pool_init( )
210 // Loop variable used to create the pools
214 pools
= mlt_properties_new( );
217 for ( i
= 8; i
< 31; i
++ )
219 // Each properties item needs a name
223 mlt_pool pool
= pool_init( 1 << i
);
226 sprintf( name
, "%d", i
);
228 // Register with properties
229 mlt_properties_set_data( pools
, name
, pool
, 0, ( mlt_destructor
)pool_close
, NULL
);
233 /** Allocate size bytes from the pool.
236 void *mlt_pool_alloc( int size
)
238 // This will be used to obtain the pool to use
239 mlt_pool pool
= NULL
;
241 // Determines the index of the pool to use
244 // Minimum size pooled is 256 bytes
245 size
= size
+ sizeof( mlt_release
);
246 while ( ( 1 << index
) < size
)
249 // Now get the pool at the index
250 pool
= mlt_properties_get_data_at( pools
, index
- 8, NULL
);
252 // Now get the real item
253 return pool_fetch( pool
);
256 /** Allocate size bytes from the pool.
259 void *mlt_pool_realloc( void *ptr
, int size
)
264 // Check if we actually have an address
267 // Get the release pointer
268 mlt_release that
= ptr
- sizeof( struct mlt_release_s
);
270 // If the current pool this ptr belongs to is big enough
271 if ( size
> that
->pool
->size
- sizeof( struct mlt_release_s
) )
274 result
= mlt_pool_alloc( size
);
277 memcpy( result
, ptr
, that
->pool
->size
- sizeof( struct mlt_release_s
) );
280 mlt_pool_release( ptr
);
291 result
= mlt_pool_alloc( size
);
297 /** Purge unused items in the pool.
300 void mlt_pool_purge( )
305 for ( i
= 0; i
< mlt_properties_count( pools
); i
++ )
308 mlt_pool
this = mlt_properties_get_data_at( pools
, i
, NULL
);
310 // Pointer to unused memory
311 void *release
= NULL
;
314 pthread_mutex_lock( &this->lock
);
316 // We'll free all unused items now
317 while ( ( release
= mlt_deque_pop_back( this->stack
) ) != NULL
)
318 free( release
- sizeof( struct mlt_release_s
) );
321 pthread_mutex_unlock( &this->lock
);
325 /** Release the allocated memory.
328 void mlt_pool_release( void *release
)
330 // Return to the pool
331 pool_return( release
);
337 void mlt_pool_close( )
339 #ifdef _MLT_POOL_CHECKS_
340 // Stats dump on close
342 fprintf( stderr
, "Usage:\n\n" );
343 for ( i
= 0; i
< mlt_properties_count( pools
); i
++ )
345 mlt_pool pool
= mlt_properties_get_data_at( pools
, i
, NULL
);
347 fprintf( stderr
, "%d: allocated %d returned %d %c\n", pool
->size
, pool
->count
, mlt_deque_count( pool
->stack
),
348 pool
->count
!= mlt_deque_count( pool
->stack
) ?
'*' : ' ' );
352 // Close the properties
353 mlt_properties_close( pools
);