/* Copyright (C) 2007 StrmnNrmn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #pragma once #ifndef UTILITY_MEMORYPOOL_H_ #define UTILITY_MEMORYPOOL_H_ // // XXXX Work in progress - don't use! // template< typename T > class CMemoryPool { enum { MaxItems = 2500 }; enum { Align = 16 }; //enum { ItemSize = sizeof( T ) };//(sizeof( T ) + (Align-1)) & ~(Align-1) }; u32 ItemSize; struct Chunk { Chunk * Next; }; //struct _A{ DAEDALUS_STATIC_ASSERT( sizeof( Chunk ) == 4 ); }; //struct _B{ DAEDALUS_STATIC_ASSERT( ItemSize >= sizeof( T ) ); }; //struct _C{ DAEDALUS_STATIC_ASSERT( ItemSize >= sizeof( Chunk ) ); }; public: CMemoryPool() : ItemSize( (sizeof( T ) + (Align-1)) & ~(Align-1) ) , mMemory( new u8[ MaxItems * ItemSize ] ) { Chunk * first( NULL ); // Add chunks in reverse order for( s32 i = MaxItems - 1; i >= 0; --i ) { Chunk * chunk( reinterpret_cast< Chunk *>( &mMemory[ i * ItemSize ] ) ); chunk->Next = first; first = chunk; } mFirstFree = first; } ~CMemoryPool() { delete [] mMemory; } inline T * Allocate() { static bool said= false; if( !said ) { printf( "Item size: %d->%d, MaxItems %d\n", sizeof( T ), ItemSize, MaxItems ); said = true; } Chunk * chunk( mFirstFree ); if( chunk != NULL ) { mFirstFree = chunk->Next; #ifdef _DEBUG memset( chunk, 0xcd, ItemSize ); #endif } return reinterpret_cast< T * >( chunk ); } inline void Deallocate( void * ptr ) { DAEDALUS_ASSERT( ptr == NULL || ptr >= mMemory && ptr < &mMemory[MaxItems * ItemSize], "Trying to free block outside of our chunk" ); if( ptr != NULL ) { Chunk * chunk( reinterpret_cast< Chunk * >( ptr ) ); #ifdef _DEBUG memset( chunk, 0xdd, ItemSize ); #endif chunk->Next = mFirstFree; mFirstFree = chunk; } } private: u8 * mMemory; Chunk * mFirstFree; }; // // stl compatible allocator // // // Specialisation for , avoiding void references // template class CMemoryPoolAllocator; template <> class CMemoryPoolAllocator { public: typedef void * pointer; typedef const void * const_pointer; typedef void value_type; template < class U > struct rebind { typedef CMemoryPoolAllocator other; }; }; template< typename T > class CMemoryPoolAllocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T * pointer; typedef const T * const_pointer; typedef T & reference; typedef const T & const_reference; typedef T value_type; template< class U > struct rebind { typedef CMemoryPoolAllocator< U > other; }; CMemoryPoolAllocator() {} CMemoryPoolAllocator( const CMemoryPoolAllocator< T > & ) {} template< typename U > CMemoryPoolAllocator( const CMemoryPoolAllocator< U > & ) {} size_type max_size() const throw() { return 1; } pointer address( reference x ) const { return &x; } const_pointer address( const_reference x ) const { return &x; } pointer allocate( size_type size, CMemoryPoolAllocator::const_pointer hint = 0 ) const { if( size == 1 ) { return mPool.Allocate(); } DAEDALUS_ERROR( "Can't handle multiple allocations - don't use this allocator e.g. with std::vector" ); return NULL; } void deallocate( pointer p, size_type n ) const { DAEDALUS_ASSERT( n == 1, "Deallocating multiple items?" ); for( u32 i = 0; i < n; ++i ) { mPool.Deallocate( p ); } } void construct( pointer p, const T & val ) { new( p ) T( val ); } void construct( pointer p ) { new( p ) T(); } void destroy( pointer p ) { p->~T(); } private: static CMemoryPool< T > mPool; }; template< typename T > CMemoryPool< T > CMemoryPoolAllocator< T >::mPool; template< typename T, typename U > inline bool operator==( const CMemoryPoolAllocator< T > &, const CMemoryPoolAllocator< U > & ) { return true; } template< typename T, typename U > inline bool operator!=( const CMemoryPoolAllocator< T > &, const CMemoryPoolAllocator< U > & ) { return false; } #endif // UTILITY_MEMORYPOOL_H_