+/* Fifo */
+struct hb_fifo_s
+{
+ hb_lock_t * lock;
+ uint32_t capacity;
+ uint32_t size;
+ uint32_t buffer_size;
+ hb_buffer_t * first;
+ hb_buffer_t * last;
+};
+
+/* we round the requested buffer size up to the next power of 2 so there can
+ * be at most 32 possible pools when the size is a 32 bit int. To avoid a lot
+ * of slow & error-prone run-time checking we allow for all 32. */
+#define MAX_BUFFER_POOLS 32
+/* the buffer pool only exists to avoid the two malloc and two free calls that
+ * it would otherwise take to allocate & free a buffer. but we don't want to
+ * tie up a lot of memory in the pool because this allocator isn't as general
+ * as malloc so memory tied up here puts more pressure on the malloc pool.
+ * A pool of 16 elements will avoid 94% of the malloc/free calls without wasting
+ * too much memory. */
+#define BUFFER_POOL_MAX_ELEMENTS 32
+
+struct hb_buffer_pools_s
+{
+ int64_t allocated;
+ hb_lock_t *lock;
+ hb_fifo_t *pool[MAX_BUFFER_POOLS];
+} buffers;
+
+
+void hb_buffer_pool_init( void )
+{
+ buffers.lock = hb_lock_init();
+ buffers.allocated = 0;
+
+ /* we allocate pools for sizes 2^10 through 2^25. requests larger than
+ * 2^25 will get passed through to malloc. */
+ int i;
+ for ( i = 10; i < 26; ++i )
+ {
+ buffers.pool[i] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS);
+ buffers.pool[i]->buffer_size = 1 << i;
+ }
+ /* requests smaller than 2^10 are satisfied from the 2^10 pool. */
+ for ( i = 1; i < 10; ++i )
+ {
+ buffers.pool[i] = buffers.pool[10];
+ }
+}
+
+void hb_buffer_pool_free( void )
+{
+ int i;
+ int count;
+ int64_t freed = 0;
+ hb_buffer_t *b;
+
+ hb_lock(buffers.lock);
+
+ for( i = 10; i < 26; ++i)
+ {
+ count = 0;
+ while( ( b = hb_fifo_get(buffers.pool[i]) ) )
+ {
+ freed += b->alloc;
+ if( b->data )
+ {
+ free( b->data );
+ }
+ free( b );
+ count++;
+ }
+ if ( count )
+ {
+ hb_deep_log( 2, "Freed %d buffers of size %d", count,
+ buffers.pool[i]->buffer_size);
+ }
+ }
+
+ hb_deep_log( 2, "Allocated %lld bytes of buffers on this pass and Freed %lld bytes, "
+ "%lld bytes leaked", buffers.allocated, freed, buffers.allocated - freed);
+ buffers.allocated = 0;
+ hb_unlock(buffers.lock);
+}
+
+static hb_fifo_t *size_to_pool( int size )
+{
+ int i;
+ for ( i = 0; i < 30; ++i )
+ {
+ if ( size <= (1 << i) )
+ {
+ return buffers.pool[i];
+ }
+ }
+ return NULL;
+}
+