Skip to content
Snippets Groups Projects
Commit d14d2644 authored by Oliver Sander's avatar Oliver Sander
Browse files

remove the non-standard allocators smallobject.hh and polyallocator.hh

[[Imported from SVN: r6343]]
parent ed34ac8f
No related branches found
No related tags found
No related merge requests found
......@@ -63,7 +63,6 @@ commoninclude_HEADERS = \
nullptr.hh \
parametertree.hh \
path.hh \
polyallocator.hh \
poolallocator.hh \
precision.hh \
propertymap.hh \
......@@ -71,7 +70,6 @@ commoninclude_HEADERS = \
shared_ptr.hh \
singleton.hh \
sllist.hh \
smallobject.hh \
static_assert.hh \
stdstreams.hh \
timer.hh \
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_POLYALLOCATOR_HH
#define DUNE_POLYALLOCATOR_HH
#include <cstdlib>
#include <memory>
namespace Dune
{
// PolyAllocator
// -------------
struct PolyAllocator
{
template< class T >
T *create ( const T &value )
{
return new T( value );
}
template< class T >
void destroy ( T *p )
{
delete p;
}
};
// STLPolyAllocator
// ----------------
/** This PolyAllocator tries to use an STL allocator to create polymorphic
* objects (i.e., where the type on create differs from the type on destroy).
*
* Note: It is totally unclear whether this works or is in any way conforming
* to the standard. See FS#766 for details.
*/
template< class A = std::allocator< void > >
struct STLPolyAllocator
{
explicit STLPolyAllocator ( const A &a = A() )
: allocator_( a )
{}
template< class T >
T *create ( const T &value )
{
typename A::template rebind< T >::other allocator( allocator_ );
T *p = allocator.allocate( 1 );
allocator.construct( p, value );
return p;
}
template< class T >
void destroy ( T *p )
{
typename A::template rebind< T >::other allocator( allocator_ );
allocator.destroy( p );
allocator.deallocate( p, 1 );
}
private:
typename A::template rebind< void * >::other allocator_;
};
}
#endif // #ifndef DUNE_POLYALLOCATOR_HH
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_SMALLOBJECT_HH
#define DUNE_SMALLOBJECT_HH
#include <cassert>
#include <new>
namespace Dune
{
// SmallObjectPool
// ---------------
class SmallObjectPool
{
union Block
{
Block *next;
unsigned int blocks;
};
public:
enum { blockSize = sizeof( Block ) };
enum { maxBlocks = (1 << 10) - 1 };
enum { maxSize = maxBlocks * blockSize };
private:
Block *list_[ maxBlocks ];
SmallObjectPool ()
{
for( unsigned int i = 0; i < maxBlocks; ++i )
list_[ i ] = 0;
}
~SmallObjectPool ()
{
for( unsigned int i = 0; i < maxBlocks; ++i )
{
for( Block *next = list_[ i ]; next != 0; )
{
Block *current = next;
next = current->next;
delete[] current;
}
}
}
static SmallObjectPool &instance ()
{
static SmallObjectPool inst;
return inst;
}
static Block *&list ( unsigned int blocks )
{
assert( blocks < maxBlocks );
return instance().list_[ blocks ];
}
public:
static void *allocate ( unsigned int size )
{
const unsigned int blocks = (size + (blockSize-1)) / blockSize;
if( blocks >= maxBlocks )
return 0;
Block *&next = list( blocks );
Block *current = next;
if( current != 0 )
next = current->next;
else
current = new Block[ blocks+1 ];
current->blocks = blocks;
return current + 1;
}
static void free ( void *p )
{
if( p != 0 )
{
Block *current = reinterpret_cast< Block * >( p ) - 1;
const unsigned int blocks = current->blocks;
Block *&next = list( blocks );
current->next = next;
next = current;
}
}
};
// SmallObject
// -----------
struct SmallObject
{
void *operator new ( size_t size )
{
return SmallObjectPool::allocate( size );
}
void operator delete ( void *p )
{
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(); }
};
// SmallObjectPolyAllocator
// ------------------------
struct SmallObjectPolyAllocator
{
template< class T > T *create ( const T &value );
template< class T > void destroy ( T *p );
};
// Implementation of SmallObjectAllocator
// --------------------------------------
template< class T >
inline typename SmallObjectAllocator< T >::pointer
SmallObjectAllocator< T >::allocate ( size_type n, SmallObjectAllocator< void >::const_pointer hint )
{
return static_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;
}
// Implementation of SmallObjectPolyAllocator
// ------------------------------------------
template< class T >
inline T *SmallObjectPolyAllocator::create ( const T &value )
{
void *address = SmallObjectPool::allocate( sizeof( T ) );
return new( address ) T( value );
}
template< class T >
inline void SmallObjectPolyAllocator::destroy ( T *p )
{
p->~T();
SmallObjectPool::free( p );
}
}
#endif // #ifndef DUNE_SMALLOBJECT_HH
......@@ -26,12 +26,10 @@ TESTPROGS = \
nullptr-test \
pathtest \
paramtreetest \
polyallocator \
poolallocatortest \
shared_ptrtest_config \
shared_ptrtest_dune \
singletontest \
smallobject \
static_assert_test \
streamtest \
test-stack \
......@@ -82,8 +80,6 @@ pathtest_SOURCES = pathtest.cc
paramtreetest_SOURCES = paramtreetest.cc
smallobject_SOURCES = smallobject.cc
bitsetvectortest_SOURCES = bitsetvectortest.cc
nullptr_test_SOURCES = nullptr-test.cc nullptr-test2.cc
......@@ -144,8 +140,6 @@ fmatrixtest_LDADD = $(LAPACK_LIBS) $(LDADD)
fvectortest_SOURCES = fvectortest.cc
polyallocator_SOURCES = polyallocator.cc
poolallocatortest_SOURCES = poolallocatortest.cc
enumsettest_SOURCES=enumsettest.cc
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#include <config.h>
#include <iostream>
#include <memory>
#include <dune/common/poolallocator.hh>
#include <dune/common/polyallocator.hh>
// A test of the PolyAllocator as used in the GenericGeometries:
// struct A -> HybridMapping
// struct B,C -> VirtualMapping, i.e., HybridMappingImpl
// struct G -> BasicGeometry
struct A
{
virtual ~A () {}
virtual void test ( ) = 0;
};
struct B
: public A
{
B( int i ) : k( i ) {}
void test ( )
{
std::cout << "B( " << k << " ).test( )" << std::endl;
}
private:
int k;
};
struct C
: public A
{
void test ( )
{
std::cout << "C.test( )" << std::endl;
}
};
template <class Allocator>
struct G
{
explicit G( int k, const Allocator &alloc = Allocator() ) :
alloc_(alloc)
{
if( k>0 )
a_ = alloc_.create( B( k ) );
else
a_ = alloc_.create( C() );
}
~G()
{
alloc_.destroy( a_ );
}
void test()
{
a_->test();
}
private:
Allocator alloc_;
A *a_;
};
template< class Allocator >
struct H
{
explicit H ( int k, const Allocator &alloc = Allocator() )
: alloc_( alloc )
{
if( k > 0 )
create< B >( B( k ) );
else
create< C >( C() );
}
~H()
{
destroy_( *this );
}
void test()
{
a_->test();
}
private:
template< class Impl >
void create ( const Impl &impl )
{
typename Allocator::template rebind< Impl >::other alloc( alloc_ );
Impl *p = alloc.allocate( 1 );
alloc.construct( p, impl );
a_ = p;
destroy_ = destroy< Impl >;
}
template< class Impl >
static void destroy ( H &h )
{
typename Allocator::template rebind< Impl >::other alloc( h.alloc_ );
alloc.destroy( (Impl*)h.a_ );
alloc.deallocate( (Impl*)h.a_, 1 );
}
typedef void (*Destroy)( H &h );
Allocator alloc_;
A *a_;
Destroy destroy_;
};
int main ( int argc, char **argv )
{
int k = 0;
if( argc > 1 )
k = atoi(argv[1]);
{
G<Dune::PolyAllocator> g(k);
g.test();
}
{
H< std::allocator< A > > h( k );
h.test();
}
if( argc > 2 )
{
const int numLoops = atoi( argv[ 2 ] );
for( int i = 0; i < numLoops; ++i )
{
G< Dune::STLPolyAllocator< Dune::PoolAllocator< A, 4096 > > > g( k );
g.test();
}
}
return 0;
}
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <iostream>
#include <dune/common/timer.hh>
#include <dune/common/smallobject.hh>
#include <dune/common/poolallocator.hh>
using namespace Dune;
class A
{
int a_;
public:
A( int a )
: a_( a )
{}
};
class B
: public SmallObject
{
int b_;
public:
B( int b )
: b_( b )
{}
};
int main ( int argc, char **argv )
{
Timer timer;
const unsigned long iterations = 1 << 7;
const unsigned long factor = 16;
std :: cout << "Performing " << (factor*iterations) << " iterations." << std :: endl;
timer.reset();
for( unsigned long i = 0; i < iterations; ++i )
{
A *a = new A( (int)i );
delete a;
}
double timeA = factor*timer.elapsed();
std :: cout << "Time without SmallObject: " << timeA << std :: endl;
timer.reset();
for( unsigned long i = 0; i < factor*iterations; ++i )
{
B *b = new B( (int)i );
delete b;
}
double timeB = timer.elapsed();
std :: cout << "Time with SmallObject: " << timeB << std :: endl;
std :: cout << "Result: SmallObject is " << (timeA / timeB) << " times faster." << std :: endl;
timer.reset();
SmallObjectAllocator< A > alloc;
for( unsigned long i = 0; i < factor*iterations; ++i )
{
A *a = alloc.allocate( 1 );
alloc.construct( a, A( int( i ) ) );
alloc.destroy( a );
alloc.deallocate( a, 1 );
}
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);
// we require the speed of the poolallocator
// assert((timeB2 / timeB) > 1.0);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment