diff options
Diffstat (limited to 'include/EASTL/core_allocator_adapter.h')
-rw-r--r-- | include/EASTL/core_allocator_adapter.h | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/include/EASTL/core_allocator_adapter.h b/include/EASTL/core_allocator_adapter.h new file mode 100644 index 0000000..d6f1827 --- /dev/null +++ b/include/EASTL/core_allocator_adapter.h @@ -0,0 +1,368 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) Electronic Arts Inc. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Implements an EASTL allocator that uses an ICoreAllocator. +// However, this header file is not dependent on ICoreAllocator or its package. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_H +#define EASTL_CORE_ALLOCATOR_ADAPTER_H + +#if EASTL_CORE_ALLOCATOR_ENABLED + + +#include <EASTL/internal/config.h> + +#if defined(EA_PRAGMA_ONCE_SUPPORTED) + #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. +#endif + + +/// EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR +/// +/// This allows the application to override the default name for the default global core allocator. +/// However, you must be careful in your usage of this, as if this file is shared between uses then +/// you will need to be careful that your override of this doesn't conflict with others. +/// +#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR + #define EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR AllocatorType::GetDefaultAllocator +#endif + + + +namespace EA +{ + namespace Allocator + { + /// CoreAllocatorAdapter + /// + /// Implements the EASTL allocator interface. + /// Allocates memory from an instance of ICoreAllocator or another class with an equivalent interface. + /// ICoreAllocator is a pure-virtual memory allocation interface used by a number of EA games and + /// shared libraries. It's completely unrelated to EASTL, but it's prevalent enough that it's useful + /// for EASTL to have a built-in adapter for this interface. ICoreAllocator is declared in the + /// CoreAllocator package icoreallocator_interface.h header, but CoreAllocatorAdapter can work with + /// any equivalent interface, as defined below. + /// + /// Expected interface: + /// enum AllocFlags { + /// kFlagTempMemory = 0, + /// kFlagPermMemory = 1 + /// }; + /// + /// struct CoreAllocator { + /// void* Alloc(size_t size, const char* name, unsigned int allocFlags); + /// void* Alloc(size_t size, const char* name, unsigned int allocFlags, // Not required unless you are working with types that require custom alignment. + /// unsigned int align, unsigned int alignOffset = 0); + /// void Free(void* block, size_t size = 0); + /// static CoreAllocator* GetDefaultAllocator(); + /// }; + /// + /// Example usage: + /// #include <coreallocator/icoreallocator_interface.h> + /// typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter; + /// eastl::list<Widget, Adapter> widgetList(Adapter("UI/WidgetList", pSomeCoreAllocator)); + /// widgetList.push_back(Widget()); + /// + /// Example usage: + /// #include <MyEquivalentCoreAllocatorInterface.h> + /// eastl::list<Widget, CoreAllocatorAdapter<MyCoreAllocatorInterface> > widgetList; + /// widgetList.push_back(Widget()); + /// + /// Example usage: + /// #include <coreallocator/icoreallocator_interface.h> + /// typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter; + /// typedef eastl::list<Widget, Adapter> WidgetList; + /// CoreAllocatorFixed<WidgetList::node_type> widgetCoreAllocator(pFixedAllocatorForWidgetListValueType); // CoreAllocatorFixed is a hypothetical implementation of the ICoreAllocator interface. + /// WidgetList widgetList(Adapter("UI/WidgetList", &widgetCoreAllocator)); // Note that the widgetCoreAllocator is declared before and thus destroyed after the widget list. + /// + template<class AllocatorType> + class CoreAllocatorAdapter + { + public: + typedef CoreAllocatorAdapter<AllocatorType> this_type; + + public: + // To do: Make this constructor explicit, when there is no known code dependent on it being otherwise. + CoreAllocatorAdapter(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME), AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR()); + CoreAllocatorAdapter(const char* pName, AllocatorType* pAllocator, int flags); + CoreAllocatorAdapter(const CoreAllocatorAdapter& x); + CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* pName); + + CoreAllocatorAdapter& operator=(const CoreAllocatorAdapter& x); + + void* allocate(size_t n, int flags = 0); + void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0); + void deallocate(void* p, size_t n); + + AllocatorType* get_allocator() const; + void set_allocator(AllocatorType* pAllocator); + + int get_flags() const; + void set_flags(int flags); + + const char* get_name() const; + void set_name(const char* pName); + + public: // Public because otherwise VC++ generates (possibly invalid) warnings about inline friend template specializations. + AllocatorType* mpCoreAllocator; + int mnFlags; // Allocation flags. See ICoreAllocator/AllocFlags. + + #if EASTL_NAME_ENABLED + const char* mpName; // Debug name, used to track memory. + #endif + }; + + template<class AllocatorType> + bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b); + + template<class AllocatorType> + bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b); + + + + /// EASTLICoreAllocator + /// + /// Provides a standardized typedef for ICoreAllocator; + /// + /// Example usage: + /// eastl::list<Widget, EASTLICoreAllocator> widgetList("UI/WidgetList", pSomeCoreAllocator); + /// widgetList.push_back(Widget()); + /// + class ICoreAllocator; + class EASTLCoreAllocatorImpl; + + typedef CoreAllocatorAdapter<ICoreAllocator> EASTLICoreAllocatorAdapter; + typedef CoreAllocatorAdapter<EASTLCoreAllocatorImpl> EASTLCoreAllocatorAdapter; + typedef EASTLICoreAllocatorAdapter EASTLICoreAllocator; // for backwards compatibility + + + + /// EASTLICoreDeleter + /// + /// Implements a functor which can free memory from the specified + /// ICoreAllocator interface. This is a convenience object provided for + /// users who wish to have EASTL containers deallocate memory obtained from + /// ICoreAllocator interfaces. + /// + template <class AllocatorType> + class CoreDeleterAdapter + { + public: + typedef CoreDeleterAdapter<AllocatorType> this_type; + AllocatorType* mpCoreAllocator; + + public: + CoreDeleterAdapter(AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR()) EA_NOEXCEPT + : mpCoreAllocator(pAllocator) {} + + ~CoreDeleterAdapter() EA_NOEXCEPT {} + + template <typename T> + void operator()(T* p) + { + p->~T(); + mpCoreAllocator->Free(p); + } + + CoreDeleterAdapter(const CoreDeleterAdapter& in) { mpCoreAllocator = in.mpCoreAllocator; } + + CoreDeleterAdapter(CoreDeleterAdapter&& in) + { + mpCoreAllocator = in.mpCoreAllocator; + in.mpCoreAllocator = nullptr; + } + + CoreDeleterAdapter& operator=(const CoreDeleterAdapter& in) + { + mpCoreAllocator = in.mpCoreAllocator; + return *this; + } + + CoreDeleterAdapter& operator=(CoreDeleterAdapter&& in) + { + mpCoreAllocator = in.mpCoreAllocator; + in.mpCoreAllocator = nullptr; + return *this; + } + }; + + + + /// EASTLICoreDeleter + /// + /// Provides a standardized typedef for ICoreAllocator implementations. + /// + /// Example usage: + /// eastl::shared_ptr<A> foo(pA, EASTLCoreDeleter()); + /// + typedef CoreDeleterAdapter<ICoreAllocator> EASTLICoreDeleterAdapter; + typedef CoreDeleterAdapter<EASTLCoreAllocatorImpl> EASTLCoreDeleterAdapter; + + } // namespace Allocator + +} // namespace EA + + + + + +/////////////////////////////////////////////////////////////////////////////// +// Inlines +/////////////////////////////////////////////////////////////////////////////// + +namespace EA +{ + namespace Allocator + { + template<class AllocatorType> + inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator) + : mpCoreAllocator(pCoreAllocator), mnFlags(0) + { + #if EASTL_NAME_ENABLED + mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME; + #endif + } + + template<class AllocatorType> + inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator, int flags) + : mpCoreAllocator(pCoreAllocator), mnFlags(flags) + { + #if EASTL_NAME_ENABLED + mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME; + #endif + } + + template<class AllocatorType> + inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x) + : mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags) + { + #if EASTL_NAME_ENABLED + mpName = x.mpName; + #endif + } + + template<class AllocatorType> + inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* EASTL_NAME(pName)) + : mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags) + { + #if EASTL_NAME_ENABLED + mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME; + #endif + } + + template<class AllocatorType> + inline CoreAllocatorAdapter<AllocatorType>& CoreAllocatorAdapter<AllocatorType>::operator=(const CoreAllocatorAdapter& x) + { + mpCoreAllocator = x.mpCoreAllocator; + mnFlags = x.mnFlags; + + #if EASTL_NAME_ENABLED + mpName = x.mpName; + #endif + + return *this; + } + + template<class AllocatorType> + inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, int /*flags*/) + { + // It turns out that EASTL itself doesn't use the flags parameter, + // whereas the user here might well want to specify a flags + // parameter. So we use ours instead of the one passed in. + return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags); + } + + template<class AllocatorType> + inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, size_t alignment, size_t offset, int /*flags*/) + { + // It turns out that EASTL itself doesn't use the flags parameter, + // whereas the user here might well want to specify a flags + // parameter. So we use ours instead of the one passed in. + return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags, (unsigned)alignment, (unsigned)offset); + } + + template<class AllocatorType> + inline void CoreAllocatorAdapter<AllocatorType>::deallocate(void* p, size_t n) + { + return mpCoreAllocator->Free(p, n); + } + + template<class AllocatorType> + inline AllocatorType* CoreAllocatorAdapter<AllocatorType>::get_allocator() const + { + return mpCoreAllocator; + } + + template<class AllocatorType> + inline void CoreAllocatorAdapter<AllocatorType>::set_allocator(AllocatorType* pAllocator) + { + mpCoreAllocator = pAllocator; + } + + template<class AllocatorType> + inline int CoreAllocatorAdapter<AllocatorType>::get_flags() const + { + return mnFlags; + } + + template<class AllocatorType> + inline void CoreAllocatorAdapter<AllocatorType>::set_flags(int flags) + { + mnFlags = flags; + } + + template<class AllocatorType> + inline const char* CoreAllocatorAdapter<AllocatorType>::get_name() const + { + #if EASTL_NAME_ENABLED + return mpName; + #else + return EASTL_ALLOCATOR_DEFAULT_NAME; + #endif + } + + template<class AllocatorType> + inline void CoreAllocatorAdapter<AllocatorType>::set_name(const char* pName) + { + #if EASTL_NAME_ENABLED + mpName = pName; + #else + (void)pName; + #endif + } + + + + template<class AllocatorType> + inline bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b) + { + return (a.mpCoreAllocator == b.mpCoreAllocator) && + (a.mnFlags == b.mnFlags); + } + + template<class AllocatorType> + inline bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b) + { + return (a.mpCoreAllocator != b.mpCoreAllocator) || + (a.mnFlags != b.mnFlags); + } + + + } // namespace Allocator + +} // namespace EA + + +#endif // EASTL_CORE_ALLOCATOR_ENABLED +#endif // Header include guard + + + + + + + + |