d58d02cabddda0bc7dab3664614d31176fc2c9a5
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 fprintf( stderr
, "Usage:\n\n" );
348 for ( i
= 0; i
< mlt_properties_count( pools
); i
++ )
350 mlt_pool pool
= mlt_properties_get_data_at( pools
, i
, NULL
);
352 fprintf( stderr
, "%d: allocated %d returned %d %c\n", 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
);