aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/fixed_allocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/fixed_allocator.h')
-rw-r--r--include/EASTL/fixed_allocator.h455
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