1 /* $Id: fifo.c,v 1.17 2005/10/15 18:05:03 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
24 #define MAX_BUFFER_POOLS 15
25 #define BUFFER_POOL_MAX_ELEMENTS 2048
27 struct hb_buffer_pools_s
31 hb_fifo_t *pool[MAX_BUFFER_POOLS];
35 struct hb_buffer_pools_s buffers;
37 void hb_buffer_pool_init( void )
39 hb_fifo_t *buffer_pool;
41 int max_size = 32768;;
44 buffers.lock = hb_lock_init();
45 buffers.allocated = 0;
47 while(size <= max_size) {
48 buffer_pool = buffers.pool[buffers.entries++] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS);
49 buffer_pool->buffer_size = size;
54 void hb_buffer_pool_free( void )
61 hb_lock(buffers.lock);
63 for( i = 0; i < buffers.entries; i++)
66 while( ( b = hb_fifo_get(buffers.pool[i]) ) )
77 hb_log("Freed %d buffers of size %d", count, buffers.pool[i]->buffer_size);
80 hb_log("Allocated %d bytes of buffers on this pass and Freed %d bytes, %d bytes leaked",
81 buffers.allocated, freed, buffers.allocated - freed);
82 buffers.allocated = 0;
83 hb_unlock(buffers.lock);
87 hb_buffer_t * hb_buffer_init( int size )
91 hb_fifo_t *buffer_pool = NULL;
97 * The buffer pools are allocated in increasing size
99 for( i = 0; i < buffers.entries; i++ )
101 if( buffers.pool[i]->buffer_size >= size )
104 * This pool is big enough, but are there any buffers in it?
106 if( hb_fifo_size( buffers.pool[i] ) )
109 * We've found a matching buffer pool, with buffers.
111 buffer_pool = buffers.pool[i];
112 resize = buffers.pool[i]->buffer_size;
115 * Buffer pool is empty,
119 * This is the second time through, so break out of here to avoid
120 * using too large a buffer for a small job.
124 resize = buffers.pool[i]->buffer_size;
130 * Don't reuse the 0 size buffers, not much gain.
132 if( size != 0 && buffer_pool )
134 b = hb_fifo_get( buffer_pool );
139 * Zero the contents of the buffer, would be nice if we
140 * didn't have to do this.
142 hb_log("Reused buffer size %d for size %d from pool %d depth %d",
143 b->alloc, size, smallest_pool->buffer_size,
144 hb_fifo_size(smallest_pool));
148 memset( b, 0, sizeof(hb_buffer_t) );
157 * No existing buffers, create a new one
159 if( !( b = calloc( sizeof( hb_buffer_t ), 1 ) ) )
161 hb_log( "out of memory" );
174 hb_log("Allocating new buffer of size %d for size %d",
181 #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
182 b->data = malloc( b->alloc );
183 #elif defined( SYS_CYGWIN )
185 b->data = malloc( b->alloc + 17 );
187 b->data = memalign( 16, b->alloc );
192 hb_log( "out of memory" );
197 buffers.allocated += b->alloc;
202 void hb_buffer_realloc( hb_buffer_t * b, int size )
204 /* No more alignment, but we don't care */
208 b->data = realloc( b->data, size );
209 buffers.allocated -= b->alloc;
211 buffers.allocated += b->alloc;
214 void hb_buffer_close( hb_buffer_t ** _b )
216 hb_buffer_t * b = *_b;
217 hb_fifo_t *buffer_pool = NULL;
221 * Put the buffer into our free list in the matching buffer pool, if there is one.
225 for( i = 0; i < buffers.entries; i++ )
227 if( b->alloc == buffers.pool[i]->buffer_size )
229 buffer_pool = buffers.pool[i];
237 if( !hb_fifo_is_full( buffer_pool ) )
242 hb_log("Putting a buffer of size %d on pool %d, depth %d",
244 buffer_pool->buffer_size,
245 hb_fifo_size(buffer_pool));
247 hb_fifo_push( buffer_pool, b );
253 * Got a load of these size ones already, free this buffer.
255 hb_log("Buffer pool for size %d full, freeing buffer", b->alloc);
261 buffers.allocated -= b->alloc;
266 * Need a new buffer pool for this size.
268 hb_lock(buffers.lock);
269 if ( b->alloc != 0 && buffers.entries < MAX_BUFFER_POOLS)
271 buffer_pool = buffers.pool[buffers.entries++] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS);
272 buffer_pool->buffer_size = b->alloc;
273 hb_fifo_push( buffer_pool, b );
275 hb_log("*** Allocated a new buffer pool for size %d [%d]", b->alloc,
281 for( i = buffers.entries-1; i >= 0; i-- )
283 if( hb_fifo_size(buffers.pool[i]) == 0 )
286 * Reuse this pool as it is empty.
288 buffers.pool[i]->buffer_size = b->alloc;
289 hb_fifo_push( buffers.pool[i], b );
302 buffers.allocated -= b->alloc;
307 hb_unlock(buffers.lock);
314 void hb_buffer_copy_settings( hb_buffer_t * dst, const hb_buffer_t * src )
316 dst->start = src->start;
317 dst->stop = src->stop;
318 dst->new_chap = src->new_chap;
319 dst->frametype = src->frametype;
320 dst->flags = src->flags;
323 hb_fifo_t * hb_fifo_init( int capacity )
326 f = calloc( sizeof( hb_fifo_t ), 1 );
327 f->lock = hb_lock_init();
328 f->capacity = capacity;
333 int hb_fifo_size( hb_fifo_t * f )
339 hb_unlock( f->lock );
344 int hb_fifo_is_full( hb_fifo_t * f )
349 ret = ( f->size >= f->capacity );
350 hb_unlock( f->lock );
355 float hb_fifo_percent_full( hb_fifo_t * f )
360 ret = f->size / f->capacity;
361 hb_unlock( f->lock );
366 hb_buffer_t * hb_fifo_get( hb_fifo_t * f )
373 hb_unlock( f->lock );
380 hb_unlock( f->lock );
385 hb_buffer_t * hb_fifo_see( hb_fifo_t * f )
392 hb_unlock( f->lock );
396 hb_unlock( f->lock );
401 hb_buffer_t * hb_fifo_see2( hb_fifo_t * f )
408 hb_unlock( f->lock );
412 hb_unlock( f->lock );
417 void hb_fifo_push( hb_fifo_t * f, hb_buffer_t * b )
435 while( f->last->next )
438 f->last = f->last->next;
440 hb_unlock( f->lock );
443 void hb_fifo_close( hb_fifo_t ** _f )
448 hb_log( "fifo_close: trashing %d buffer(s)", hb_fifo_size( f ) );
449 while( ( b = hb_fifo_get( f ) ) )
451 hb_buffer_close( &b );
454 hb_lock_close( &f->lock );