diff options
Diffstat (limited to 'include/EASTL/fixed_allocator.h')
-rw-r--r-- | include/EASTL/fixed_allocator.h | 455 |
1 files changed, 0 insertions, 455 deletions
diff --git a/include/EASTL/fixed_allocator.h b/include/EASTL/fixed_allocator.h deleted file mode 100644 index 488eae4..0000000 --- a/include/EASTL/fixed_allocator.h +++ /dev/null @@ -1,455 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Copyright (c) Electronic Arts Inc. All rights reserved. -///////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -// This file implements the following -// fixed_allocator -// fixed_allocator_with_overflow -/////////////////////////////////////////////////////////////////////////////// - - -#ifndef EASTL_FIXED_ALLOCATOR_H -#define EASTL_FIXED_ALLOCATOR_H - - -#include <EASTL/internal/config.h> -#include <EASTL/internal/fixed_pool.h> -#include <EASTL/functional.h> -#include <EASTL/memory.h> -#include <EASTL/allocator.h> -#include <EASTL/type_traits.h> - -EA_DISABLE_ALL_VC_WARNINGS(); - -#include <new> - -EA_RESTORE_ALL_VC_WARNINGS(); - -EA_DISABLE_VC_WARNING(4275); // non dll-interface class used as base for DLL-interface classkey 'identifier' - -#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 - - - -namespace eastl -{ - - /////////////////////////////////////////////////////////////////////////// - // fixed_allocator - /////////////////////////////////////////////////////////////////////////// - - /// fixed_allocator - /// - /// Implements an allocator which allocates a single fixed size where - /// the size, alignment, and memory used for the pool is defined at - /// runtime by the user. This is different from fixed containers - /// such as fixed_list whereby the size and alignment are determined - /// at compile time and the memory is directly built into the container's - /// member data. - /// - /// If the pool's memory is exhausted or was never initialized, the - /// allocate function returns NULL. Consider the fixed_allocator_with_overflow - /// class as an alternative in order to deal with this situation. - /// - /// This class requires the user to call container.get_allocator().init() - /// after constructing the container. There currently isn't a way to - /// construct the container with the initialization parameters, though - /// with some effort such a thing could probably be made possible. - /// It's not as simple as it might first seem, due to the non-copyable - /// nature of fixed allocators. A side effect of this limitation is that - /// you cannot copy-construct a container using fixed_allocators. - /// - /// Another side-effect is that you cannot swap two containers using - /// a fixed_allocator, as a swap requires temporary memory allocated by - /// an equivalent allocator, and such a thing cannot be done implicitly. - /// A workaround for the swap limitation is that you can implement your - /// own swap whereby you provide an explicitly created temporary object. - /// - /// Note: Be careful to set the allocator's node size to the size of the - /// container node and not the size of the contained object. Note that the - /// example code below uses IntListNode. - /// - /// Example usage: - /// typedef eastl::list<int, fixed_allocator> IntList; - /// typedef IntList::node_type IntListNode; - /// - /// IntListNode buffer[200]; - /// IntList intList; - /// intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode)); - /// - class EASTL_API fixed_allocator : public fixed_pool_base - { - public: - /// fixed_allocator - /// - /// Default constructor. The user usually will need to call init() after - /// constructing via this constructor. - /// - fixed_allocator(const char* /*pName*/ = EASTL_FIXED_POOL_DEFAULT_NAME) - : fixed_pool_base(NULL) - { - } - - - /// fixed_allocator - /// - /// Copy constructor. The user usually will need to call init() after - /// constructing via this constructor. By their nature, fixed-allocators - /// cannot be copied in any useful way, as by their nature the user - /// must manually initialize them. - /// - fixed_allocator(const fixed_allocator&) - : fixed_pool_base(NULL) - { - } - - - /// operator= - /// - /// By their nature, fixed-allocators cannot be copied in any - /// useful way, as by their nature the user must manually - /// initialize them. - /// - fixed_allocator& operator=(const fixed_allocator&) - { - return *this; - } - - - // init - // - // No init here, as the base class version is sufficient. - // - //void init(void* pMemory, size_t memorySize, size_t nodeSize, - // size_t alignment, size_t alignmentOffset = 0); - - - /// allocate - /// - /// Allocates a new object of the size specified upon class initialization. - /// Returns NULL if there is no more memory. - /// - void* allocate(size_t n, int /*flags*/ = 0) - { - // To consider: Verify that 'n' is what the user initialized us with. - - Link* pLink = mpHead; - - if(pLink) // If we have space... - { - #if EASTL_FIXED_SIZE_TRACKING_ENABLED - if(++mnCurrentSize > mnPeakSize) - mnPeakSize = mnCurrentSize; - #endif - - mpHead = pLink->mpNext; - return pLink; - } - else - { - // If there's no free node in the free list, just - // allocate another from the reserved memory area - - if(mpNext != mpCapacity) - { - pLink = mpNext; - - mpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + n); - - #if EASTL_FIXED_SIZE_TRACKING_ENABLED - if(++mnCurrentSize > mnPeakSize) - mnPeakSize = mnCurrentSize; - #endif - - return pLink; - } - - // EASTL_ASSERT(false); To consider: enable this assert. However, we intentionally disable it because this isn't necessarily an assertable error. - return NULL; - } - } - - - /// allocate - /// - void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0) - { - return allocate(n, flags); - } - - - /// deallocate - /// - /// Frees the given object which was allocated by allocate(). - /// If the given node was not allocated by allocate() then the behaviour - /// is undefined. - /// - void deallocate(void* p, size_t) - { - #if EASTL_FIXED_SIZE_TRACKING_ENABLED - --mnCurrentSize; - #endif - - ((Link*)p)->mpNext = mpHead; - mpHead = ((Link*)p); - } - - - using fixed_pool_base::can_allocate; - - - const char* get_name() const - { - return EASTL_FIXED_POOL_DEFAULT_NAME; - } - - - void set_name(const char*) - { - // Nothing to do. We don't allocate memory. - } - - }; // fixed_allocator - - bool operator==(const fixed_allocator& a, const fixed_allocator& b); - bool operator!=(const fixed_allocator& a, const fixed_allocator& b); - - - - /////////////////////////////////////////////////////////////////////////// - // fixed_allocator_with_overflow - /////////////////////////////////////////////////////////////////////////// - - /// fixed_allocator_with_overflow - /// - /// Implements an allocator which allocates a single fixed size where - /// the size, alignment, and memory used for the pool is defined at - /// runtime by the user. This is different from fixed containers - /// such as fixed_list whereby the size and alignment are determined - /// at compile time and the memory is directly built into the container's - /// member data. - /// - /// Note: Be careful to set the allocator's node size to the size of the - /// container node and not the size of the contained object. Note that the - /// example code below uses IntListNode. - /// - /// This class requires the user to call container.get_allocator().init() - /// after constructing the container. There currently isn't a way to - /// construct the container with the initialization parameters, though - /// with some effort such a thing could probably be made possible. - /// It's not as simple as it might first seem, due to the non-copyable - /// nature of fixed allocators. A side effect of this limitation is that - /// you cannot copy-construct a container using fixed_allocators. - /// - /// Another side-effect is that you cannot swap two containers using - /// a fixed_allocator, as a swap requires temporary memory allocated by - /// an equivalent allocator, and such a thing cannot be done implicitly. - /// A workaround for the swap limitation is that you can implement your - /// own swap whereby you provide an explicitly created temporary object. - /// - /// Example usage: - /// typedef eastl::list<int, fixed_allocator_with_overflow> IntList; - /// typedef IntList::node_type IntListNode; - /// - /// IntListNode buffer[200]; - /// IntList intList; - /// intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode)); - /// - class EASTL_API fixed_allocator_with_overflow : public fixed_pool_base - { - public: - /// fixed_allocator_with_overflow - /// - /// Default constructor. The user usually will need to call init() after - /// constructing via this constructor. - /// - fixed_allocator_with_overflow(const char* pName = EASTL_FIXED_POOL_DEFAULT_NAME) - : fixed_pool_base(NULL) - , mOverflowAllocator(pName) - , mpPoolBegin(nullptr) - , mpPoolEnd(nullptr) - , mnNodeSize(0) - { - } - - - /// fixed_allocator_with_overflow - /// - /// Copy constructor. The user usually will need to call init() after - /// constructing via this constructor. By their nature, fixed-allocators - /// cannot be copied in any useful way, as by their nature the user - /// must manually initialize them. - /// - fixed_allocator_with_overflow(const fixed_allocator_with_overflow&) - : fixed_pool_base(NULL) - , mpPoolBegin(nullptr) - , mpPoolEnd(nullptr) - , mnNodeSize(0) - { - } - - - /// operator= - /// - /// By their nature, fixed-allocators cannot be copied in any - /// useful way, as by their nature the user must manually - /// initialize them. - /// - fixed_allocator_with_overflow& operator=(const fixed_allocator_with_overflow& x) - { - #if EASTL_ALLOCATOR_COPY_ENABLED - mOverflowAllocator = x.mOverflowAllocator; - #else - (void)x; - #endif - - return *this; - } - - - /// init - /// - void init(void* pMemory, size_t memorySize, size_t nodeSize, - size_t alignment, size_t alignmentOffset = 0) - { - fixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset); - - mpPoolBegin = pMemory; - mpPoolEnd = (void*)((uintptr_t)pMemory + memorySize); - mnNodeSize = (eastl_size_t)nodeSize; - } - - - /// allocate - /// - /// Allocates a new object of the size specified upon class initialization. - /// Returns NULL if there is no more memory. - /// - void* allocate(size_t /*n*/, int /*flags*/ = 0) - { - // To consider: Verify that 'n' is what the user initialized us with. - - void* p; - - if(mpHead) // If we have space... - { - p = mpHead; - mpHead = mpHead->mpNext; - } - else - { - // If there's no free node in the free list, just - // allocate another from the reserved memory area - - if (mpNext != mpCapacity) - { - p = mpNext; - mpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + mnNodeSize); - } - else - p = mOverflowAllocator.allocate(mnNodeSize); - } - - #if EASTL_FIXED_SIZE_TRACKING_ENABLED - if(p && (++mnCurrentSize > mnPeakSize)) - mnPeakSize = mnCurrentSize; - #endif - - return p; - } - - - /// allocate - /// - void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0) - { - return allocate(n, flags); - } - - - /// deallocate - /// - /// Frees the given object which was allocated by allocate(). - /// If the given node was not allocated by allocate() then the behaviour - /// is undefined. - /// - void deallocate(void* p, size_t) - { - #if EASTL_FIXED_SIZE_TRACKING_ENABLED - --mnCurrentSize; - #endif - - if((p >= mpPoolBegin) && (p < mpPoolEnd)) - { - ((Link*)p)->mpNext = mpHead; - mpHead = ((Link*)p); - } - else - mOverflowAllocator.deallocate(p, (size_t)mnNodeSize); - } - - - using fixed_pool_base::can_allocate; - - - const char* get_name() const - { - return mOverflowAllocator.get_name(); - } - - - void set_name(const char* pName) - { - mOverflowAllocator.set_name(pName); - } - - protected: - EASTLAllocatorType mOverflowAllocator; // To consider: Allow the user to define the type of this, presumably via a template parameter. - void* mpPoolBegin; // To consider: We have these member variables and ideally we shouldn't need them. The problem is that - void* mpPoolEnd; // the information about the pool buffer and object size is stored in the owning container - eastl_size_t mnNodeSize; // and we can't have access to it without increasing the amount of code we need and by templating - // more code. It may turn out that simply storing data here is smaller in the end. - }; // fixed_allocator_with_overflow // Granted, this class is usually used for debugging purposes, but perhaps there is an elegant solution. - - bool operator==(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b); - bool operator!=(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b); - - - - - - - /////////////////////////////////////////////////////////////////////// - // global operators - /////////////////////////////////////////////////////////////////////// - - inline bool operator==(const fixed_allocator&, const fixed_allocator&) - { - return false; - } - - inline bool operator!=(const fixed_allocator&, const fixed_allocator&) - { - return false; - } - - inline bool operator==(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&) - { - return false; - } - - inline bool operator!=(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&) - { - return false; - } - - -} // namespace eastl - - -EA_RESTORE_VC_WARNING(); - -#endif // Header include guard |