00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_SMALLOBJ_INC_
00016 #define LOKI_SMALLOBJ_INC_
00017
00018
00019
00020
00021 #include "LokiExport.h"
00022 #include "Threads.h"
00023 #include "Singleton.h"
00024 #include <cstddef>
00025 #include <new>
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;
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;
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
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;
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;
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;
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;
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;
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;
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;
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;
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 };
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 };
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 };
00640
00641 }
00642
00643 #endif // end file guardian
00644