diff options
author | archshift <admin@archshift.com> | 2014-07-29 22:04:00 +0200 |
---|---|---|
committer | archshift <admin@archshift.com> | 2014-07-29 22:04:00 +0200 |
commit | a9b597087b56b4526a3f6447789ba141568575a1 (patch) | |
tree | a08542d77b5668a25ca5e00492577ed6f4d61a9a /src/AllocationPool.h | |
parent | Spacing fixes and a few more BLOCK_META constants. (diff) | |
parent | Slight cleanup after portals (diff) | |
download | cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar.gz cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar.bz2 cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar.lz cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar.xz cuberite-a9b597087b56b4526a3f6447789ba141568575a1.tar.zst cuberite-a9b597087b56b4526a3f6447789ba141568575a1.zip |
Diffstat (limited to 'src/AllocationPool.h')
-rw-r--r-- | src/AllocationPool.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/AllocationPool.h b/src/AllocationPool.h new file mode 100644 index 000000000..3c9dbe8c9 --- /dev/null +++ b/src/AllocationPool.h @@ -0,0 +1,113 @@ + +#pragma once + +#include <memory> + +template<class T> +class cAllocationPool +{ +public: + class cStarvationCallbacks + { + public: + virtual ~cStarvationCallbacks() {} + + /** Is called when the reserve buffer starts to be used **/ + virtual void OnStartUsingReserve() = 0; + + /** Is called once the reserve buffer has returned to normal size **/ + virtual void OnEndUsingReserve() = 0; + + /** Is called when the allocation pool is unable to allocate memory. Will be repeatedly + called if it does not free sufficient memory **/ + virtual void OnOutOfReserve() = 0; + }; + + virtual ~cAllocationPool() {} + + /** Allocates a pointer to T **/ + virtual T * Allocate() = 0; + + /** Frees the pointer passed in a_ptr, invalidating it **/ + virtual void Free(T * a_ptr) = 0; +}; + +/** Allocates memory storing unused elements in a linked list. Keeps at least NumElementsInReserve +elements in the list unless malloc fails so that the program has a reserve to handle OOM.**/ +template<class T, size_t NumElementsInReserve> +class cListAllocationPool : public cAllocationPool<T> +{ + public: + + cListAllocationPool(std::auto_ptr<typename cAllocationPool<T>::cStarvationCallbacks> a_Callbacks) : + m_Callbacks(a_Callbacks) + { + for (size_t i = 0; i < NumElementsInReserve; i++) + { + void * space = malloc(sizeof(T)); + if (space == NULL) + { + m_Callbacks->OnStartUsingReserve(); + break; + } + m_FreeList.push_front(space); + } + } + + virtual ~cListAllocationPool() + { + while (!m_FreeList.empty()) + { + free (m_FreeList.front()); + m_FreeList.pop_front(); + } + } + + virtual T * Allocate() override + { + if (m_FreeList.size() <= NumElementsInReserve) + { + void * space = malloc(sizeof(T)); + if (space != NULL) + { + return new(space) T; + } + else if (m_FreeList.size() == NumElementsInReserve) + { + m_Callbacks->OnStartUsingReserve(); + } + else if (m_FreeList.empty()) + { + m_Callbacks->OnOutOfReserve(); + // Try again until the memory is avalable + return Allocate(); + } + } + // placement new, used to initalize the object + T * ret = new (m_FreeList.front()) T; + m_FreeList.pop_front(); + return ret; + } + virtual void Free(T * a_ptr) override + { + if (a_ptr == NULL) + { + return; + } + // placement destruct. + a_ptr->~T(); + m_FreeList.push_front(a_ptr); + if (m_FreeList.size() == NumElementsInReserve) + { + m_Callbacks->OnEndUsingReserve(); + } + } + + private: + std::list<void *> m_FreeList; + std::auto_ptr<typename cAllocationPool<T>::cStarvationCallbacks> m_Callbacks; +}; + + + + |