diff --git a/dune/common/smallobject.hh b/dune/common/smallobject.hh index 2b34260b2edd9a0ae7dc635b83e1dbc523917377..3f4d0b33cb7fb01aa74c2bc3fe6452812833be4d 100644 --- a/dune/common/smallobject.hh +++ b/dune/common/smallobject.hh @@ -75,11 +75,11 @@ namespace Dune return current + 1; } - static void free ( void *ptr ) + static void free ( void *p ) { - if( ptr != 0 ) + if( p != 0 ) { - Block *current = reinterpret_cast< Block * >( ptr ) - 1; + Block *current = reinterpret_cast< Block * >( p ) - 1; const unsigned int blocks = current->blocks; Block *&next = list( blocks ); current->next = next; @@ -97,15 +97,97 @@ namespace Dune { void *operator new ( size_t size ) { - return SmallObjectPool :: allocate( size ); + return SmallObjectPool::allocate( size ); } - void operator delete ( void *ptr ) + void operator delete ( void *p ) { - SmallObjectPool :: free( ptr ); + SmallObjectPool::free( p ); } }; + + + // SmallObjectAllocator + // -------------------- + + template< class T > + struct SmallObjectAllocator; + + template<> + struct SmallObjectAllocator< void > + { + typedef void value_type; + + typedef void *pointer; + typedef const void *const_pointer; + + template< class U > struct rebind { typedef SmallObjectAllocator< U > other; }; + }; + + template< class T > + struct SmallObjectAllocator + { + typedef T value_type; + 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; + + template< class U > struct rebind { typedef SmallObjectAllocator< U > other; }; + + SmallObjectAllocator () throw () {} + template< class U > SmallObjectAllocator ( const SmallObjectAllocator< U > & ) throw () {} + ~SmallObjectAllocator () throw () {} + + pointer address ( reference r ) const { return &r; } + const_pointer address ( const_reference r ) const { return &r; } + + pointer allocate ( size_type n, SmallObjectAllocator< void >::const_pointer hint = 0 ); + void deallocate ( pointer p, size_type n ); + + void construct ( pointer p, const T &value ) { new( p ) T( value ); } + void destroy ( pointer p ) { p->~T(); } + }; + + + + // Implementation of SmallObjectAllocator + // -------------------------------------- + + template< class T > + inline typename SmallObjectAllocator< T >::pointer + SmallObjectAllocator< T >::allocate ( size_type n, SmallObjectAllocator< void >::const_pointer hint ) + { + return reinterpret_cast< pointer >( SmallObjectPool::allocate( n * sizeof( T ) ) ); + } + + + template< class T > + inline void + SmallObjectAllocator< T >::deallocate ( pointer p, size_type n ) + { + SmallObjectPool::free( p ); + } + + + template< class T > + bool operator== ( const SmallObjectAllocator< T > &, const SmallObjectAllocator< T > & ) throw() + { + return true; + } + + + template< class T > + bool operator!= ( const SmallObjectAllocator< T > &, const SmallObjectAllocator< T > & ) throw() + { + return false; + } + } -#endif +#endif // #ifndef DUNE_SMALLOBJECT_HH diff --git a/dune/common/test/smallobject.cc b/dune/common/test/smallobject.cc index 753e4ba9bb929ec8ac6a3c8f08fc191dde0220a2..69ae3dec9c63aeafe5eb2488adf0df358798b3b7 100644 --- a/dune/common/test/smallobject.cc +++ b/dune/common/test/smallobject.cc @@ -63,18 +63,31 @@ int main ( int argc, char **argv ) std :: cout << "Result: SmallObject is " << (timeA / timeB) << " times faster." << std :: endl; timer.reset(); - PoolAllocator<B,100> pool; + SmallObjectAllocator< A > alloc; for( unsigned long i = 0; i < factor*iterations; ++i ) { - B *b = pool.allocate(1); - pool.construct(b, B((int)i )); - pool.destroy(b); - pool.deallocate(b,1); + A *a = alloc.allocate( 1 ); + alloc.construct( a, A( int( i ) ) ); + alloc.destroy( a ); + alloc.deallocate( a, 1 ); } - double timeB2 = timer.elapsed(); - std :: cout << "Time with pool allocator: " << timeB2 << std :: endl; - std :: cout << "Result: pool allocator is " << (timeA / timeB2) << " times faster." << std :: endl; - std :: cout << "Result: pool allocator is " << (timeB / timeB2) << " times faster than SmallObject." << std :: endl; + double timeC = timer.elapsed(); + std :: cout << "Time with SmallObjectAllocator: " << timeC << std :: endl; + std :: cout << "Result: SmallObject is " << (timeA / timeC) << " times faster." << std :: endl; + + timer.reset(); + PoolAllocator< A, 100 > pool; + for( unsigned long i = 0; i < factor*iterations; ++i ) + { + A *a = pool.allocate(1); + pool.construct( a, A( int( i ) ) ); + pool.destroy( a ); + pool.deallocate( a, 1 ); + } + double timeD = timer.elapsed(); + std :: cout << "Time with pool allocator: " << timeD << std :: endl; + std :: cout << "Result: pool allocator is " << (timeA / timeD) << " times faster." << std :: endl; + std :: cout << "Result: pool allocator is " << (timeB / timeD) << " times faster than SmallObject." << std :: endl; // we require a speedup due to SmallObject //assert((timeA / timeB) > 1.0);