smallobject.hh
00001 #ifndef DUNE_SMALLOBJECT_HH
00002 #define DUNE_SMALLOBJECT_HH
00003
00004 #include <cassert>
00005 #include <new>
00006
00007 namespace Dune
00008 {
00009
00010
00011
00012
00013 class SmallObjectPool
00014 {
00015 union Block
00016 {
00017 Block *next;
00018 unsigned int blocks;
00019 };
00020
00021 public:
00022 enum { blockSize = sizeof( Block ) };
00023 enum { maxBlocks = (1 << 10) - 1 };
00024 enum { maxSize = maxBlocks * blockSize };
00025
00026 private:
00027 Block *list_[ maxBlocks ];
00028
00029 SmallObjectPool ()
00030 {
00031 for( unsigned int i = 0; i < maxBlocks; ++i )
00032 list_[ i ] = 0;
00033 }
00034
00035 ~SmallObjectPool ()
00036 {
00037 for( unsigned int i = 0; i < maxBlocks; ++i )
00038 {
00039 for( Block *next = list_[ i ]; next != 0; )
00040 {
00041 Block *current = next;
00042 next = current->next;
00043 delete[] current;
00044 }
00045 }
00046 }
00047
00048 static SmallObjectPool &instance ()
00049 {
00050 static SmallObjectPool inst;
00051 return inst;
00052 }
00053
00054 static Block *&list ( unsigned int blocks )
00055 {
00056 assert( blocks < maxBlocks );
00057 return instance().list_[ blocks ];
00058 }
00059
00060 public:
00061 static void *allocate ( unsigned int size )
00062 {
00063 const unsigned int blocks = (size + (blockSize-1)) / blockSize;
00064 if( blocks >= maxBlocks )
00065 return 0;
00066 Block *&next = list( blocks );
00067 Block *current = next;
00068 if( current != 0 )
00069 next = current->next;
00070 else
00071 current = new Block[ blocks+1 ];
00072 current->blocks = blocks;
00073 return current + 1;
00074 }
00075
00076 static void free ( void *ptr )
00077 {
00078 if( ptr != 0 )
00079 {
00080 Block *current = reinterpret_cast< Block * >( ptr ) - 1;
00081 const unsigned int blocks = current->blocks;
00082 Block *&next = list( blocks );
00083 current->next = next;
00084 next = current;
00085 }
00086 }
00087 };
00088
00089
00090
00091
00092
00093
00094 struct SmallObject
00095 {
00096 void *operator new ( size_t size )
00097 {
00098 return SmallObjectPool :: allocate( size );
00099 }
00100
00101 void operator delete ( void *ptr )
00102 {
00103 SmallObjectPool :: free( ptr );
00104 }
00105 };
00106
00107 }
00108
00109 #endif