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.fr/>.
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;
99 * The buffer pools are allocated in increasing size
101 for( i = 0; i < buffers.entries; i++ )
103 if( buffers.pool[i]->buffer_size >= size )
106 * This pool is big enough, but are there any buffers in it?
108 if( hb_fifo_size( buffers.pool[i] ) )
111 * We've found a matching buffer pool, with buffers.
113 buffer_pool = buffers.pool[i];
114 resize = buffers.pool[i]->buffer_size;
117 * Buffer pool is empty,
121 * This is the second time through, so break
122 * out of here to avoid using too large a
123 * buffer for a small job.
127 resize = buffers.pool[i]->buffer_size;
133 * Don't reuse the 0 size buffers, not much gain.
135 if( size != 0 && buffer_pool )
137 b = hb_fifo_get( buffer_pool );
142 * Zero the contents of the buffer, would be nice if we
143 * didn't have to do this.
145 hb_log("Reused buffer size %d for size %d from pool %d depth %d",
146 b->alloc, size, smallest_pool->buffer_size,
147 hb_fifo_size(smallest_pool));
151 memset( b, 0, sizeof(hb_buffer_t) );
160 * No existing buffers, create a new one
162 if( !( b = calloc( sizeof( hb_buffer_t ), 1 ) ) )
164 hb_log( "out of memory" );
177 hb_log("Allocating new buffer of size %d for size %d",
184 #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
185 b->data = malloc( b->alloc );
186 #elif defined( SYS_CYGWIN )
188 b->data = malloc( b->alloc + 17 );
190 b->data = memalign( 16, b->alloc );
195 hb_log( "out of memory" );
200 buffers.allocated += b->alloc;
205 void hb_buffer_realloc( hb_buffer_t * b, int size )
207 /* No more alignment, but we don't care */
211 b->data = realloc( b->data, size );
212 buffers.allocated -= b->alloc;
214 buffers.allocated += b->alloc;
217 void hb_buffer_close( hb_buffer_t ** _b )
219 hb_buffer_t * b = *_b;
220 hb_fifo_t *buffer_pool = NULL;
224 * Put the buffer into our free list in the matching buffer pool, if there is one.
228 for( i = 0; i < buffers.entries; i++ )
230 if( b->alloc == buffers.pool[i]->buffer_size )
232 buffer_pool = buffers.pool[i];
240 if( !hb_fifo_is_full( buffer_pool ) )
245 hb_log("Putting a buffer of size %d on pool %d, depth %d",
247 buffer_pool->buffer_size,
248 hb_fifo_size(buffer_pool));
250 hb_fifo_push( buffer_pool, b );
256 * Got a load of these size ones already, free this buffer.
258 hb_log("Buffer pool for size %d full, freeing buffer", b->alloc);
264 buffers.allocated -= b->alloc;
269 * Need a new buffer pool for this size.
271 hb_lock(buffers.lock);
272 if ( b->alloc != 0 && buffers.entries < MAX_BUFFER_POOLS)
274 buffer_pool = buffers.pool[buffers.entries++] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS);
275 buffer_pool->buffer_size = b->alloc;
276 hb_fifo_push( buffer_pool, b );
278 hb_log("*** Allocated a new buffer pool for size %d [%d]", b->alloc,
284 for( i = buffers.entries-1; i >= 0; i-- )
286 if( hb_fifo_size(buffers.pool[i]) == 0 )
289 * Reuse this pool as it is empty.
291 buffers.pool[i]->buffer_size = b->alloc;
292 hb_fifo_push( buffers.pool[i], b );
305 buffers.allocated -= b->alloc;
310 hb_unlock(buffers.lock);
317 void hb_buffer_copy_settings( hb_buffer_t * dst, const hb_buffer_t * src )
319 dst->start = src->start;
320 dst->stop = src->stop;
321 dst->new_chap = src->new_chap;
322 dst->frametype = src->frametype;
323 dst->flags = src->flags;
326 hb_fifo_t * hb_fifo_init( int capacity )
329 f = calloc( sizeof( hb_fifo_t ), 1 );
330 f->lock = hb_lock_init();
331 f->capacity = capacity;
336 int hb_fifo_size( hb_fifo_t * f )
342 hb_unlock( f->lock );
347 int hb_fifo_is_full( hb_fifo_t * f )
352 ret = ( f->size >= f->capacity );
353 hb_unlock( f->lock );
358 float hb_fifo_percent_full( hb_fifo_t * f )
363 ret = f->size / f->capacity;
364 hb_unlock( f->lock );
369 hb_buffer_t * hb_fifo_get( hb_fifo_t * f )
376 hb_unlock( f->lock );
383 hb_unlock( f->lock );
388 hb_buffer_t * hb_fifo_see( hb_fifo_t * f )
395 hb_unlock( f->lock );
399 hb_unlock( f->lock );
404 hb_buffer_t * hb_fifo_see2( hb_fifo_t * f )
411 hb_unlock( f->lock );
415 hb_unlock( f->lock );
420 void hb_fifo_push( hb_fifo_t * f, hb_buffer_t * b )
438 while( f->last->next )
441 f->last = f->last->next;
443 hb_unlock( f->lock );
446 void hb_fifo_close( hb_fifo_t ** _f )
451 hb_log( "fifo_close: trashing %d buffer(s)", hb_fifo_size( f ) );
452 while( ( b = hb_fifo_get( f ) ) )
454 hb_buffer_close( &b );
457 hb_lock_close( &f->lock );