1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6#ifndef _MEMORYPOOL_
7#define _MEMORYPOOL_
8
9#include "daccess.h"
10#include "contract.h"
11
12//
13// A MemoryPool is an allocator for a fixed size elements.
14// Allocating and freeing elements from the pool is very cheap compared
15// to a general allocator like new. However, a MemoryPool is slightly
16// more greedy - it preallocates a bunch of elements at a time, and NEVER
17// RELEASES MEMORY FROM THE POOL ONCE IT IS ALLOCATED, (unless you call
18// FreeAllElements.)
19//
20// It also has several additional features:
21// * you can free the entire pool of objects cheaply.
22// * you can test an object to see if it's an element of the pool.
23//
24
25class MemoryPool
26{
27 public:
28
29#ifndef DACCESS_COMPILE
30 MemoryPool(SIZE_T elementSize, SIZE_T initGrowth = 20, SIZE_T initCount = 0);
31#else
32 MemoryPool() {}
33#endif
34 ~MemoryPool() DAC_EMPTY();
35
36 BOOL IsElement(void *element);
37 BOOL IsAllocatedElement(void *element);
38 void *AllocateElement();
39 void *AllocateElementNoThrow();
40 void FreeElement(void *element);
41 void FreeAllElements();
42 size_t GetSize();
43 private:
44
45 struct Element
46 {
47 Element *next;
48#if _DEBUG
49 int deadBeef;
50#endif
51 };
52
53 struct Block
54 {
55 Block *next;
56 Element *elementsEnd;
57#ifdef _MSC_VER
58#pragma warning(push)
59#pragma warning(disable:4200)
60#endif
61 Element elements[0];
62#ifdef _MSC_VER
63#pragma warning(pop)
64#endif
65 };
66
67 SIZE_T m_elementSize;
68 SIZE_T m_growCount;
69 Block *m_blocks;
70 Element *m_freeList;
71
72 BOOL AddBlock(SIZE_T elementCount);
73 void DeadBeef(Element *element);
74
75 public:
76
77 //
78 // NOTE: You can currently only iterate the elements
79 // if none have been freed.
80 //
81
82 class Iterator
83 {
84 private:
85 Block *m_next;
86 BYTE *m_e, *m_eEnd;
87 BYTE *m_end;
88 SIZE_T m_size;
89
90 public:
91 Iterator(MemoryPool *pool);
92
93 BOOL Next();
94
95 void *GetElement() {LIMITED_METHOD_CONTRACT; return (void *) (m_e-m_size); }
96 };
97
98 friend class Iterator;
99};
100
101class MemoryPoolElementHolder
102{
103 protected:
104 MemoryPool* m_pool;
105 void* m_element;
106 BOOL bRelease;
107 public:
108 void SuppressRelease()
109 {
110 LIMITED_METHOD_CONTRACT;
111 _ASSERTE(bRelease);
112 bRelease=false;
113 }
114 void Release()
115 {
116 LIMITED_METHOD_CONTRACT;
117 _ASSERTE(bRelease);
118 m_pool->FreeElement(m_element);
119 bRelease=false;
120 }
121 MemoryPoolElementHolder(MemoryPool* pool, void* element)
122 {
123 LIMITED_METHOD_CONTRACT;
124 m_pool=pool;
125 m_element=element;
126 bRelease=true;
127 }
128
129 ~MemoryPoolElementHolder()
130 {
131 LIMITED_METHOD_CONTRACT;
132 if (bRelease)
133 Release();
134 }
135
136 operator void* ()
137 {
138 LIMITED_METHOD_CONTRACT;
139 return m_element;
140 }
141};
142
143#endif // _MEMORYPOOL_
144