summaryrefslogtreecommitdiff
path: root/src/inc/memorypool.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/memorypool.h')
-rw-r--r--src/inc/memorypool.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/inc/memorypool.h b/src/inc/memorypool.h
new file mode 100644
index 0000000000..9ea524f1f2
--- /dev/null
+++ b/src/inc/memorypool.h
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#ifndef _MEMORYPOOL_
+#define _MEMORYPOOL_
+
+#include "daccess.h"
+#include "contract.h"
+
+//
+// A MemoryPool is an allocator for a fixed size elements.
+// Allocating and freeing elements from the pool is very cheap compared
+// to a general allocator like new. However, a MemoryPool is slightly
+// more greedy - it preallocates a bunch of elements at a time, and NEVER
+// RELEASES MEMORY FROM THE POOL ONCE IT IS ALLOCATED, (unless you call
+// FreeAllElements.)
+//
+// It also has several additional features:
+// * you can free the entire pool of objects cheaply.
+// * you can test an object to see if it's an element of the pool.
+//
+
+class MemoryPool
+{
+ public:
+
+#ifndef DACCESS_COMPILE
+ MemoryPool(SIZE_T elementSize, SIZE_T initGrowth = 20, SIZE_T initCount = 0);
+#else
+ MemoryPool() {}
+#endif
+ ~MemoryPool() DAC_EMPTY();
+
+ BOOL IsElement(void *element);
+ BOOL IsAllocatedElement(void *element);
+ void *AllocateElement();
+ void *AllocateElementNoThrow();
+ void FreeElement(void *element);
+ void FreeAllElements();
+ size_t GetSize();
+ private:
+
+ struct Element
+ {
+ Element *next;
+#if _DEBUG
+ int deadBeef;
+#endif
+ };
+
+ struct Block
+ {
+ Block *next;
+ Element *elementsEnd;
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4200)
+#endif
+ Element elements[0];
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ };
+
+ SIZE_T m_elementSize;
+ SIZE_T m_growCount;
+ Block *m_blocks;
+ Element *m_freeList;
+
+ BOOL AddBlock(SIZE_T elementCount);
+ void DeadBeef(Element *element);
+
+ public:
+
+ //
+ // NOTE: You can currently only iterate the elements
+ // if none have been freed.
+ //
+
+ class Iterator
+ {
+ private:
+ Block *m_next;
+ BYTE *m_e, *m_eEnd;
+ BYTE *m_end;
+ SIZE_T m_size;
+
+ public:
+ Iterator(MemoryPool *pool);
+
+ BOOL Next();
+
+ void *GetElement() {LIMITED_METHOD_CONTRACT; return (void *) (m_e-m_size); }
+ };
+
+ friend class Iterator;
+};
+
+class MemoryPoolElementHolder
+{
+ protected:
+ MemoryPool* m_pool;
+ void* m_element;
+ BOOL bRelease;
+ public:
+ void SuppressRelease()
+ {
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(bRelease);
+ bRelease=false;
+ }
+ void Release()
+ {
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(bRelease);
+ m_pool->FreeElement(m_element);
+ bRelease=false;
+ }
+ MemoryPoolElementHolder(MemoryPool* pool, void* element)
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_pool=pool;
+ m_element=element;
+ bRelease=true;
+ }
+
+ ~MemoryPoolElementHolder()
+ {
+ LIMITED_METHOD_CONTRACT;
+ if (bRelease)
+ Release();
+ }
+
+ operator void* ()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_element;
+ }
+};
+
+#endif // _MEMORYPOOL_