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
;
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
);