summaryrefslogtreecommitdiffstats
path: root/src/AllocationPool.h
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2014-06-21 23:14:23 +0200
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2014-06-21 23:14:23 +0200
commit7615ed90c020b88db52b0b094f00cd028e326b5a (patch)
treeca7f647e77195a6346a2333f3d9fe5292cd2ed40 /src/AllocationPool.h
parentFixed invalid iterators (diff)
parentMerge branch 'master' of https://github.com/mc-server/MCServer (diff)
downloadcuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar.gz
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar.bz2
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar.lz
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar.xz
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.tar.zst
cuberite-7615ed90c020b88db52b0b094f00cd028e326b5a.zip
Diffstat (limited to 'src/AllocationPool.h')
-rw-r--r--src/AllocationPool.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/AllocationPool.h b/src/AllocationPool.h
new file mode 100644
index 000000000..5d749a79e
--- /dev/null
+++ b/src/AllocationPool.h
@@ -0,0 +1,109 @@
+
+#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;
+};