| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- #pragma once
- #undef min
- #undef max
- #include <boost/preprocessor.hpp>
- namespace CamelotFramework
- {
- /**
- * @brief Memory allocator providing a generic implementation.
- * Specialize for specific categories as needed.
- */
- template<class T>
- class MemoryAllocator
- {
- public:
- static inline void* allocate(UINT32 bytes)
- {
- return malloc(bytes);
- }
- static inline void* allocateArray(UINT32 bytes, UINT32 count)
- {
- return malloc(bytes * count);
- }
- static inline void free(void* ptr)
- {
- ::free(ptr);
- }
- static inline void freeArray(void* ptr, UINT32 count)
- {
- ::free(ptr);
- }
- };
- /**
- * @brief General allocator provided by the OS. Use for persistent long term allocations,
- * and allocations that don't happen often.
- */
- class GenAlloc
- { };
- /**
- * @brief Allocator used for allocating small amounts of temporary memory that
- * used and then quickly released
- */
- class ScratchAlloc
- { };
- /**
- * @brief Pool allocator that is only suited for allocating one specific type of data. Most useful when you are
- * often allocating one certain data type, with no specific allocation or deallocation order.
- */
- class PoolAlloc
- { };
- /**
- * @brief Allocates the specified number of bytes.
- */
- template<class Alloc>
- inline void* cm_alloc(UINT32 count)
- {
- return MemoryAllocator<Alloc>::allocate(count);
- }
- /**
- * @brief Allocates enough bytes to hold the specified type, but doesn't construct it.
- */
- template<class T, class Alloc>
- inline T* cm_alloc()
- {
- return (T*)MemoryAllocator<Alloc>::allocate(sizeof(T));
- }
- /**
- * @brief Creates and constructs an array of "count" elements.
- */
- template<class T, class Alloc>
- inline T* cm_newN(UINT32 count)
- {
- T* ptr = (T*)MemoryAllocator<Alloc>::allocateArray(sizeof(T), count);
- for(unsigned int i = 0; i < count; i++)
- new ((void*)&ptr[i]) T;
- return ptr;
- }
- /**
- * @brief Create a new object with the specified allocator and the specified parameters.
- */
- #define MAKE_CM_NEW(z, n, unused) \
- template<class Type, class Alloc BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
- Type* cm_new(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t) ) { \
- return new (cm_alloc<Alloc>(sizeof(Type))) Type(BOOST_PP_ENUM_PARAMS (n, t)); \
- }
- BOOST_PP_REPEAT_FROM_TO(1, 15, MAKE_CM_NEW, ~)
- #undef MAKE_CM_NEW
- // Create a new object with the specified allocator without any parameters
- // (Needs to be separate from parameter version so I don't unnecessarily zero-initialize POD types)
- template<class Type, class Alloc>
- Type* cm_new()
- {
- return new (cm_alloc<Alloc>(sizeof(Type))) Type;
- }
- /**
- * @brief Frees all the bytes allocated at the specified location.
- */
- template<class Alloc>
- inline void cm_free(void* ptr)
- {
- MemoryAllocator<Alloc>::free(ptr);
- }
- /**
- * @brief Destructs and frees the specified object.
- */
- template<class Alloc, class T>
- inline void cm_delete(T* ptr)
- {
- (ptr)->~T();
- MemoryAllocator<Alloc>::free(ptr);
- }
- /**
- * @brief Destructs and frees the specified array of objects.
- */
- template<class Alloc, class T>
- inline void cm_deleteN(T* ptr, UINT32 count)
- {
- for(unsigned int i = 0; i < count; i++)
- ptr[i].~T();
- MemoryAllocator<Alloc>::freeArray(ptr, count);
- }
- /*****************************************************************************/
- /* Default versions of all alloc/free/new/delete methods which call GenAlloc */
- /*****************************************************************************/
- /**
- * @brief Allocates the specified number of bytes.
- */
- inline void* cm_alloc(UINT32 count)
- {
- return MemoryAllocator<GenAlloc>::allocate(count);
- }
- /**
- * @brief Allocates enough bytes to hold the specified type, but doesn't construct it.
- */
- template<class T>
- inline T* cm_alloc()
- {
- return (T*)MemoryAllocator<GenAlloc>::allocate(sizeof(T));
- }
- /**
- * @brief Creates and constructs an array of "count" elements.
- */
- template<class T>
- inline T* cm_newN(UINT32 count)
- {
- T* ptr = (T*)MemoryAllocator<GenAlloc>::allocateArray(sizeof(T), count);
- for(unsigned int i = 0; i < count; i++)
- new ((void*)&ptr[i]) T;
- return ptr;
- }
- // Create a new object with the general allocator and the specified parameters.
- #define MAKE_CM_NEW(z, n, unused) \
- template<class Type BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
- Type* cm_new(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t) ) { \
- return new (cm_alloc<GenAlloc>(sizeof(Type))) Type(BOOST_PP_ENUM_PARAMS (n, t)); \
- }
- BOOST_PP_REPEAT_FROM_TO(1, 15, MAKE_CM_NEW, ~)
- #undef MAKE_CM_NEW
- // Create a new object with the general allocator without any parameters
- // (Needs to be separate from parameter version so I don't unnecessarily zero-initialize POD types)
- template<class Type>
- Type* cm_new()
- {
- return new (cm_alloc<GenAlloc>(sizeof(Type))) Type;
- }
- /**
- * @brief Frees all the bytes allocated at the specified location.
- */
- inline void cm_free(void* ptr)
- {
- MemoryAllocator<GenAlloc>::free(ptr);
- }
- /**
- * @brief Destructs and frees the specified object.
- */
- template<class T>
- inline void cm_delete(T* ptr)
- {
- (ptr)->~T();
- MemoryAllocator<GenAlloc>::free(ptr);
- }
- /**
- * @brief Destructs and frees the specified array of objects.
- */
- template<class T>
- inline void cm_deleteN(T* ptr, UINT32 count)
- {
- for(unsigned int i = 0; i < count; i++)
- ptr[i].~T();
- MemoryAllocator<GenAlloc>::freeArray(ptr, count);
- }
- }
- namespace CamelotFramework
- {
- // Allocator we can use in the standard library
- template <class T, class Alloc = GenAlloc>
- class StdAlloc
- {
- public:
- // type definitions
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
- // rebind allocator to type U
- template <class U>
- struct rebind
- {
- typedef StdAlloc<U, Alloc> other;
- };
- // return address of values
- pointer address (reference value) const
- {
- return &value;
- }
- const_pointer address (const_reference value) const
- {
- return &value;
- }
- /* constructors and destructor
- * - nothing to do because the allocator has no state
- */
- StdAlloc() throw()
- { }
- StdAlloc(const StdAlloc&) throw()
- { }
- template <class U>
- StdAlloc (const StdAlloc<U, Alloc>&) throw()
- { }
- ~StdAlloc() throw()
- { }
- // return maximum number of elements that can be allocated
- size_type max_size () const throw()
- {
- return std::numeric_limits<std::size_t>::max() / sizeof(T);
- }
- // allocate but don't initialize num elements of type T
- pointer allocate (size_type num, const void* = 0)
- {
- pointer ret = (pointer)(cm_alloc<Alloc>((UINT32)num*sizeof(T)));
- return ret;
- }
- // initialize elements of allocated storage p with value value
- void construct (pointer p, const T& value)
- {
- // initialize memory with placement new
- new((void*)p)T(value);
- }
- // destroy elements of initialized storage p
- void destroy (pointer p)
- {
- // destroy objects by calling their destructor
- p->~T();
- }
- // deallocate storage p of deleted elements
- void deallocate (pointer p, size_type num)
- {
- // print message and deallocate memory with global delete
- cm_free<Alloc>((void*)p);
- }
- };
- // return that all specializations of this allocator are interchangeable
- template <class T1, class T2, class Alloc>
- bool operator== (const StdAlloc<T1, Alloc>&,
- const StdAlloc<T2, Alloc>&) throw() {
- return true;
- }
- template <class T1, class T2, class Alloc>
- bool operator!= (const StdAlloc<T1, Alloc>&,
- const StdAlloc<T2, Alloc>&) throw() {
- return false;
- }
- }
- #include "CmMemStack.h"
|