//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2008 by Rich Sposato // // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author makes no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_ALLOCATOR_HPP_INCLUDED #define LOKI_ALLOCATOR_HPP_INCLUDED // $Id$ // Requires project to be compiled with loki/src/SmallObj.cpp and loki/src/Singleton.cpp #include namespace Loki { //----------------------------------------------------------------------------- /** @class LokiAllocator Adapts Loki's Small-Object Allocator for STL container classes. This class provides all the functionality required for STL allocators, but uses Loki's Small-Object Allocator to perform actual memory operations. Implementation comes from a post in Loki forums (by Rasmus Ekman?). */ template < typename Type, typename AllocT = Loki::AllocatorSingleton<> > class LokiAllocator { public: typedef ::std::size_t size_type; typedef ::std::ptrdiff_t difference_type; typedef Type * pointer; typedef const Type * const_pointer; typedef Type & reference; typedef const Type & const_reference; typedef Type value_type; /// Default constructor does nothing. inline LokiAllocator( void ) throw() { } /// Copy constructor does nothing. inline LokiAllocator( const LokiAllocator & ) throw() { } /// Type converting allocator constructor does nothing. template < typename Type1 > inline LokiAllocator( const LokiAllocator< Type1 > & ) throw() { } /// Destructor does nothing. inline ~LokiAllocator() throw() { } /// Convert an allocator to an allocator . template < typename Type1 > struct rebind { typedef LokiAllocator< Type1 > other; }; /// Return address of reference to mutable element. pointer address( reference elem ) const { return &elem; } /// Return address of reference to const element. const_pointer address( const_reference elem ) const { return &elem; } /** Allocate an array of count elements. Warning! The true parameter in the call to Allocate means this function can throw exceptions. This is better than not throwing, and returning a null pointer in case the caller assumes the return value is not null. @param count # of elements in array. @param hint Place where caller thinks allocation should occur. @return Pointer to block of memory. */ pointer allocate( size_type count, const void * hint = 0 ) { (void)hint; // Ignore the hint. void * p = AllocT::Instance().Allocate( count * sizeof( Type ), true ); return reinterpret_cast< pointer >( p ); } /// Ask allocator to release memory at pointer with size bytes. void deallocate( pointer p, size_type size ) { AllocT::Instance().Deallocate( p, size * sizeof( Type ) ); } /// Calculate max # of elements allocator can handle. size_type max_size( void ) const throw() { // A good optimizer will see these calculations always produce the same // value and optimize this function away completely. const size_type max_bytes = size_type( -1 ); const size_type bytes = max_bytes / sizeof( Type ); return bytes; } /// Construct an element at the pointer. void construct( pointer p, const Type & value ) { // A call to global placement new forces a call to copy constructor. ::new( p ) Type( value ); } /// Destruct the object at pointer. void destroy( pointer p ) { // If the Type has no destructor, then some compilers complain about // an unreferenced parameter, so use the void cast trick to prevent // spurious warnings. (void)p; p->~Type(); } }; //----------------------------------------------------------------------------- /** All equality operators return true since LokiAllocator is basically a monostate design pattern, so all instances of it are identical. */ template < typename Type > inline bool operator == ( const LokiAllocator< Type > &, const LokiAllocator< Type > & ) { return true; } /** All inequality operators return false since LokiAllocator is basically a monostate design pattern, so all instances of it are identical. */ template < typename Type > inline bool operator != ( const LokiAllocator< Type > & , const LokiAllocator< Type > & ) { return false; } //----------------------------------------------------------------------------- } // namespace Loki #endif // LOKI_ALLOCATOR_INCLUDED