medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 3c52cb7f64b84ac0e2467c9282e40b8c6d20a46e
parent 326f30b0c0d486e3a11fe647279fb7d58fd7d981
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sun Dec 11 14:18:45 +0200

Add memory pool class

Diffstat:
pool.h | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+), 0 deletions(-)
diff --git a/pool.h b/pool.h @@ -0,0 +1,113 @@ +#pragma once + +#include "intrinsics.h" +#include "array.h" + +template< typename T, u32 N > +class Pool; + +template< typename T, u32 N > +class PoolIterator { +public: + PoolIterator( Pool< T, N > * p, u32 start ) { + pool = p; + idx = start; + next = idx == Pool< T, N >::INVALID_IDX ? idx : pool->nexts[ idx ]; + } + + T * operator*() { + return &pool->elems[ idx ]; + } + + bool operator!=( PoolIterator< T, N > other ) { + return idx != other.idx || next != other.next || pool != other.pool; + } + + void operator++() { + idx = next; + next = idx == Pool< T, N >::INVALID_IDX ? idx : pool->nexts[ idx ]; + } + +private: + Pool< T, N > * pool; + u32 idx; + u32 next; +}; + +template< typename T, u32 N > +class Pool { +public: + Pool() { + for( u32 i = 0; i < N; i++ ) { + nexts[ i ] = i + 1; + } + nexts[ N - 1 ] = INVALID_IDX; + + first_free = 0; + first_used = INVALID_IDX; + num_used = 0; + } + + T * acquire() { + if( first_free == INVALID_IDX ) return NULL; + + u32 idx = first_free; + + // remove idx from head of the free list + first_free = nexts[ idx ]; + + // add idx to the head of the used list + nexts[ idx ] = first_used; + prev_useds[ idx ] = INVALID_IDX; + if( first_used != INVALID_IDX ) { + prev_useds[ first_used ] = idx; + } + first_used = idx; + + num_used++; + + return &elems[ idx ]; + } + + void release( T * elem ) { + u32 idx = checked_cast< u32 >( elem - elems.ptr() ); + ASSERT( idx < N ); + + // remove idx from the middle of the used list + if( nexts[ idx ] != INVALID_IDX ) { + prev_useds[ nexts[ idx ] ] = prev_useds[ idx ]; + } + if( prev_useds[ idx ] != INVALID_IDX ) { + nexts[ prev_useds[ idx ] ] = nexts[ idx ]; + } + if( first_used == idx ) { + first_used = nexts[ idx ]; + } + + // add idx to the head of the free list + nexts[ idx ] = first_free; + first_free = idx; + + num_used--; + } + + PoolIterator< T, N > begin() { + return PoolIterator< T, N >( this, first_used ); + } + + PoolIterator< T, N > end() { + return PoolIterator< T, N >( this, INVALID_IDX ); + } + +private: + enum { INVALID_IDX = U32_MAX }; + + StaticArray< T, N > elems; + StaticArray< u32, N > nexts; + StaticArray< u32, N > prev_useds; + u32 first_free; + u32 first_used; + u32 num_used; + + friend class PoolIterator< T, N >; +};