SmallObj.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Wesley Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_SMALLOBJ_INC_
00016 #define LOKI_SMALLOBJ_INC_
00017 
00018 // $Id: SmallObj.h 806 2007-02-03 00:01:52Z rich_sposato $
00019 
00020 
00021 #include "LokiExport.h"
00022 #include "Threads.h"
00023 #include "Singleton.h"
00024 #include <cstddef>
00025 #include <new> // needed for std::nothrow_t parameter.
00026 
00027 #ifndef LOKI_DEFAULT_CHUNK_SIZE
00028 #define LOKI_DEFAULT_CHUNK_SIZE 4096
00029 #endif
00030 
00031 #ifndef LOKI_MAX_SMALL_OBJECT_SIZE
00032 #define LOKI_MAX_SMALL_OBJECT_SIZE 256
00033 #endif
00034 
00035 #ifndef LOKI_DEFAULT_OBJECT_ALIGNMENT
00036 #define LOKI_DEFAULT_OBJECT_ALIGNMENT 4
00037 #endif
00038 
00039 #ifndef LOKI_DEFAULT_SMALLOBJ_LIFETIME
00040 #define LOKI_DEFAULT_SMALLOBJ_LIFETIME ::Loki::LongevityLifetime::DieAsSmallObjectParent
00041 #endif
00042 
00043 #if defined(LOKI_SMALL_OBJECT_USE_NEW_ARRAY) && defined(_MSC_VER)
00044 #pragma message("Don't define LOKI_SMALL_OBJECT_USE_NEW_ARRAY when using a Microsoft compiler to prevent memory leaks.")
00045 #pragma message("now calling '#undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY'")
00046 #undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY
00047 #endif
00048 
00053 
00054 namespace Loki
00055 {
00056     namespace LongevityLifetime
00057     {
00064         template <class T>
00065         struct DieAsSmallObjectParent  : DieLast<T> {};
00066 
00073         template <class T>
00074         struct DieAsSmallObjectChild  : DieDirectlyBeforeLast<T> {};
00075 
00076     } 
00077 
00078     class FixedAllocator;
00079 
00086     class LOKI_EXPORT SmallObjAllocator
00087     {
00088     protected:
00095         SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize,
00096             std::size_t objectAlignSize );
00097 
00103         ~SmallObjAllocator( void );
00104 
00105     public:
00135         void * Allocate( std::size_t size, bool doThrow );
00136 
00141         void Deallocate( void * p, std::size_t size );
00142 
00150         void Deallocate( void * p );
00151 
00153         inline std::size_t GetMaxObjectSize() const
00154         { return maxSmallObjectSize_; }
00155 
00157         inline std::size_t GetAlignment() const { return objectAlignSize_; }
00158 
00166         bool TrimExcessMemory( void );
00167 
00176         bool IsCorrupt( void ) const;
00177 
00178     private:
00180         SmallObjAllocator( void );
00182         SmallObjAllocator( const SmallObjAllocator & );
00184         SmallObjAllocator & operator = ( const SmallObjAllocator & );
00185 
00187         Loki::FixedAllocator * pool_;
00188 
00190         const std::size_t maxSmallObjectSize_;
00191 
00193         const std::size_t objectAlignSize_;
00194     };
00195 
00196 
00213     template
00214     <
00215         template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
00216         std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
00217         std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
00218         std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
00219         template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
00220         class MutexPolicy = LOKI_DEFAULT_MUTEX
00221     >
00222     class AllocatorSingleton : public SmallObjAllocator
00223     {
00224     public:
00225 
00227         typedef AllocatorSingleton< ThreadingModel, chunkSize,
00228             maxSmallObjectSize, objectAlignSize, LifetimePolicy > MyAllocator;
00229 
00231         typedef ThreadingModel< MyAllocator, MutexPolicy > MyThreadingModel;
00232 
00234         typedef Loki::SingletonHolder< MyAllocator, Loki::CreateStatic,
00235             LifetimePolicy, ThreadingModel > MyAllocatorSingleton;
00236 
00238         inline static AllocatorSingleton & Instance( void )
00239         {
00240             return MyAllocatorSingleton::Instance();
00241         }
00242 
00244         inline AllocatorSingleton() :
00245             SmallObjAllocator( chunkSize, maxSmallObjectSize, objectAlignSize )
00246             {}
00247 
00249         inline ~AllocatorSingleton( void ) {}
00250 
00259         static void ClearExtraMemory( void );
00260 
00269         static bool IsCorrupted( void );
00270 
00271     private:
00273         AllocatorSingleton( const AllocatorSingleton & );
00275         AllocatorSingleton & operator = ( const AllocatorSingleton & );
00276     };
00277 
00278     template
00279     <
00280         template <class, class> class T,
00281         std::size_t C,
00282         std::size_t M,
00283         std::size_t O,
00284         template <class> class L,
00285         class X
00286     >
00287     void AllocatorSingleton< T, C, M, O, L, X >::ClearExtraMemory( void )
00288     {
00289         typename MyThreadingModel::Lock lock;
00290         (void)lock; // get rid of warning
00291         Instance().TrimExcessMemory();
00292     }
00293 
00294     template
00295     <
00296         template <class, class> class T,
00297         std::size_t C,
00298         std::size_t M,
00299         std::size_t O,
00300         template <class> class L,
00301         class X
00302     >
00303     bool AllocatorSingleton< T, C, M, O, L, X >::IsCorrupted( void )
00304     {
00305         typename MyThreadingModel::Lock lock;
00306         (void)lock; // get rid of warning
00307         return Instance().IsCorrupt();
00308     }
00309 
00322     template
00323     <
00324         template <class, class> class T,
00325         std::size_t C,
00326         std::size_t M,
00327         std::size_t O,
00328         template <class> class L,
00329         class X
00330     >
00331     inline unsigned int GetLongevity(
00332         AllocatorSingleton< T, C, M, O, L, X > * )
00333     {
00334         // Returns highest possible value.
00335         return 0xFFFFFFFF;
00336     }
00337 
00338 
00427     template
00428     <
00429         template <class, class> class ThreadingModel,
00430         std::size_t chunkSize,
00431         std::size_t maxSmallObjectSize,
00432         std::size_t objectAlignSize,
00433         template <class> class LifetimePolicy,
00434         class MutexPolicy
00435     >
00436     class SmallObjectBase
00437     {
00438 
00439 #if (LOKI_MAX_SMALL_OBJECT_SIZE != 0) && (LOKI_DEFAULT_CHUNK_SIZE != 0) && (LOKI_DEFAULT_OBJECT_ALIGNMENT != 0)
00440 
00441     public:        
00444         typedef AllocatorSingleton< ThreadingModel, chunkSize,
00445             maxSmallObjectSize, objectAlignSize, LifetimePolicy > ObjAllocatorSingleton;
00446     
00447     private:
00448 
00450         typedef ThreadingModel< ObjAllocatorSingleton, MutexPolicy > MyThreadingModel;
00451 
00453         typedef typename ObjAllocatorSingleton::MyAllocatorSingleton MyAllocatorSingleton;
00454         
00455     public:
00456 
00458 #ifdef _MSC_VER
00460         static void * operator new ( std::size_t size )
00461 #else
00462         static void * operator new ( std::size_t size ) throw ( std::bad_alloc )
00463 #endif
00464         {
00465             typename MyThreadingModel::Lock lock;
00466             (void)lock; // get rid of warning
00467             return MyAllocatorSingleton::Instance().Allocate( size, true );
00468         }
00469 
00471         static void * operator new ( std::size_t size, const std::nothrow_t & ) throw ()
00472         {
00473             typename MyThreadingModel::Lock lock;
00474             (void)lock; // get rid of warning
00475             return MyAllocatorSingleton::Instance().Allocate( size, false );
00476         }
00477 
00479         inline static void * operator new ( std::size_t size, void * place )
00480         {
00481             return ::operator new( size, place );
00482         }
00483 
00485         static void operator delete ( void * p, std::size_t size ) throw ()
00486         {
00487             typename MyThreadingModel::Lock lock;
00488             (void)lock; // get rid of warning
00489             MyAllocatorSingleton::Instance().Deallocate( p, size );
00490         }
00491 
00495         static void operator delete ( void * p, const std::nothrow_t & ) throw()
00496         {
00497             typename MyThreadingModel::Lock lock;
00498             (void)lock; // get rid of warning
00499             MyAllocatorSingleton::Instance().Deallocate( p );
00500         }
00501 
00503         inline static void operator delete ( void * p, void * place )
00504         {
00505             ::operator delete ( p, place );
00506         }
00507 
00508 #ifdef LOKI_SMALL_OBJECT_USE_NEW_ARRAY
00509 
00511 #ifdef _MSC_VER
00513         static void * operator new [] ( std::size_t size )
00514 #else
00515         static void * operator new [] ( std::size_t size )
00516             throw ( std::bad_alloc )
00517 #endif
00518         {
00519             typename MyThreadingModel::Lock lock;
00520             (void)lock; // get rid of warning
00521             return MyAllocatorSingleton::Instance().Allocate( size, true );
00522         }
00523 
00525         static void * operator new [] ( std::size_t size,
00526             const std::nothrow_t & ) throw ()
00527         {
00528             typename MyThreadingModel::Lock lock;
00529             (void)lock; // get rid of warning
00530             return MyAllocatorSingleton::Instance().Allocate( size, false );
00531         }
00532 
00534         inline static void * operator new [] ( std::size_t size, void * place )
00535         {
00536             return ::operator new( size, place );
00537         }
00538 
00540         static void operator delete [] ( void * p, std::size_t size ) throw ()
00541         {
00542             typename MyThreadingModel::Lock lock;
00543             (void)lock; // get rid of warning
00544             MyAllocatorSingleton::Instance().Deallocate( p, size );
00545         }
00546 
00550         static void operator delete [] ( void * p,
00551             const std::nothrow_t & ) throw()
00552         {
00553             typename MyThreadingModel::Lock lock;
00554             (void)lock; // get rid of warning
00555             MyAllocatorSingleton::Instance().Deallocate( p );
00556         }
00557 
00559         inline static void operator delete [] ( void * p, void * place )
00560         {
00561             ::operator delete ( p, place );
00562         }
00563 #endif  // #if use new array functions.
00564 
00565 #endif  // #if default template parameters are not zero
00566 
00567     protected:
00568         inline SmallObjectBase( void ) {}
00569         inline SmallObjectBase( const SmallObjectBase & ) {}
00570         inline SmallObjectBase & operator = ( const SmallObjectBase & )
00571         { return *this; }
00572         inline ~SmallObjectBase() {}
00573     }; // end class SmallObjectBase
00574 
00575 
00585     template
00586     <
00587         template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
00588         std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
00589         std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
00590         std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
00591         template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
00592         class MutexPolicy = LOKI_DEFAULT_MUTEX
00593     >
00594     class SmallObject : public SmallObjectBase< ThreadingModel, chunkSize,
00595             maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy >
00596     {
00597 
00598     public:
00599         virtual ~SmallObject() {}
00600     protected:
00601         inline SmallObject( void ) {}
00602 
00603     private:
00605         SmallObject( const SmallObject & );
00607         SmallObject & operator = ( const SmallObject & );
00608     }; // end class SmallObject
00609 
00610 
00621     template
00622     <
00623         template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
00624         std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
00625         std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
00626         std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
00627         template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
00628         class MutexPolicy = LOKI_DEFAULT_MUTEX
00629     >
00630     class SmallValueObject : public SmallObjectBase< ThreadingModel, chunkSize,
00631             maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy >
00632     {
00633     protected:
00634         inline SmallValueObject( void ) {}
00635         inline SmallValueObject( const SmallValueObject & ) {}
00636         inline SmallValueObject & operator = ( const SmallValueObject & )
00637         { return *this; }
00638         inline ~SmallValueObject() {}
00639     }; // end class SmallValueObject
00640 
00641 } // namespace Loki
00642 
00643 #endif // end file guardian
00644 

Generated on Sun Feb 25 16:52:27 2007 for Loki by  doxygen 1.5.1-p1