1 //#include "precomp.h"
2 #include "MemoryPool.h"
3 #include <stdio.h>
4 /**************************************************************************
5 **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool
6 * ************************************************************************
7 * * Copyright (C) 2003 John Curry <john.curry@metre.net>
8 * *
9 * * This program is distributed under the terms of version 1.0 of the
10 * * Q Public License. See LICENSE.QPL for further details.
11 * *
12 * * This program is distributed in the hope that it will be useful,
13 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * *
16 * ***********************************************************************/
17 //
18 // This code was derived directly from the contributions of: Noah Booth
19 // Thanks Noah!
20 //
21 ////////////////////////////////////////////////////////////////////////////////
22 // CBuffer
23 ////////////////////////////////////////////////////////////////////////////////
24
min(unsigned int x,unsigned int y)25 unsigned int min (unsigned int x,unsigned int y){ return (x>y)?y:x; }
26
CBuffer(CMemoryPool * pPool)27 CBuffer::CBuffer(CMemoryPool* pPool) :
28 m_pPool(pPool),
29 m_dwSize(0),
30 m_pNext(NULL),
31 m_pPrev(NULL)
32 {
33 m_pBuffer = new BYTE[GetBufferSize()];
34 }
35
~CBuffer()36 CBuffer::~CBuffer()
37 {
38 if(m_pBuffer)
39 delete[] m_pBuffer;
40 }
41
Free()42 void CBuffer::Free()
43 {
44 m_pPool->Free(this);
45 }
46
GetBuffer()47 BYTE* CBuffer::GetBuffer()
48 {
49 return m_pBuffer;
50 }
51
GetBufferSize()52 unsigned int CBuffer::GetBufferSize()
53 {
54 return m_pPool->GetBufferSize();
55 }
56
GetSizeUsed()57 unsigned int CBuffer::GetSizeUsed()
58 {
59 return m_dwSize;
60 }
61
SetSizeUsed(unsigned int dwSizeUsed)62 unsigned int CBuffer::SetSizeUsed(unsigned int dwSizeUsed)
63 {
64 return m_dwSize = min(GetBufferSize(), dwSizeUsed);
65 }
66
67
68 ////////////////////////////////////////////////////////////////////////////////
69 // CMemoryPool::CBufferCollection
70 ////////////////////////////////////////////////////////////////////////////////
71
CBufferCollection()72 CBufferCollection::CBufferCollection() :
73 m_pHead(NULL),
74 m_pTail(NULL),
75 m_dwSize(0)
76 {
77 }
78
~CBufferCollection()79 CBufferCollection::~CBufferCollection()
80 {
81 Clear();
82 }
83
AddHead(CBuffer * pBuffer)84 void CBufferCollection::AddHead(CBuffer* pBuffer)
85 {
86 // The Tail for freePool was not messed up here 0 = prev<- tail ->next = 1.
87 // How does anything become the tail?
88 if(m_pHead == NULL)
89 {
90 m_pHead = m_pTail = pBuffer;
91 pBuffer->m_pNext = pBuffer->m_pPrev = NULL;
92 m_dwSize = 1;
93 }
94 else
95 {
96 pBuffer->m_pPrev = NULL;
97 pBuffer->m_pNext = m_pHead;
98 m_pHead->m_pPrev = pBuffer;
99 m_pHead = pBuffer;
100 m_dwSize++;
101 }
102 }
103
RemoveTail()104 CBuffer* CBufferCollection::RemoveTail()
105 {
106 CBuffer* pBuffer = NULL;
107 if(m_pTail != NULL)
108 {
109 pBuffer = m_pTail;
110 if(m_pTail->m_pPrev == NULL)
111 {
112 m_pHead = m_pTail = NULL;
113 m_dwSize = 0;
114 }
115 else
116 {
117 m_pTail->m_pPrev->m_pNext = NULL;
118 m_pTail = m_pTail->m_pPrev;
119 pBuffer->m_pNext = pBuffer->m_pPrev = NULL;
120 m_dwSize--;
121 }
122 }
123
124 return pBuffer;
125 }
126
Remove(CBuffer * pBuffer)127 void CBufferCollection::Remove(CBuffer* pBuffer)
128 {
129 if(pBuffer != NULL)
130 {
131 m_dwSize--;
132 if(pBuffer->m_pPrev == NULL)
133 {
134 m_pHead = pBuffer->m_pNext;
135 }
136 else
137 {
138 pBuffer->m_pPrev->m_pNext = pBuffer->m_pNext;
139 }
140
141 if(pBuffer->m_pNext == NULL)
142 {
143 m_pTail = pBuffer->m_pPrev;
144 }
145 else
146 {
147 pBuffer->m_pNext->m_pPrev = pBuffer->m_pPrev;
148 pBuffer->m_pNext = NULL;
149 }
150 pBuffer->m_pPrev = NULL;
151 }
152 }
153
Head()154 CBuffer* CBufferCollection::Head()
155 {
156 return m_pHead;
157 }
158
Tail()159 CBuffer* CBufferCollection::Tail()
160 {
161 return m_pTail;
162 }
163
Count()164 unsigned int CBufferCollection::Count()
165 {
166 return m_dwSize;
167 }
168
Clear()169 void CBufferCollection::Clear()
170 {
171 while(Count())
172 delete RemoveTail();
173 }
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // CMemoryPool
177 ////////////////////////////////////////////////////////////////////////////////
178
CMemoryPool(bool bAutoGrow,unsigned int dwBufferSize,unsigned int dwInitialCount)179 CMemoryPool::CMemoryPool(bool bAutoGrow /*=false*/, unsigned int dwBufferSize /*=4096*/, unsigned int dwInitialCount /*=1024*/) :
180 m_dwBufferSize(dwBufferSize),
181 m_dwCount(dwInitialCount),
182 m_bAutoGrow(bAutoGrow)
183 {
184 //InitializeCriticalSection(&m_critsec);
185 Enter();
186 for(unsigned int dwBuffer = 0; dwBuffer < m_dwCount; dwBuffer++)
187 {
188 CBuffer* pNewBuffer = new CBuffer(this);
189 m_freePool.AddHead(pNewBuffer);
190 }
191 Leave();
192 }
193
~CMemoryPool()194 CMemoryPool::~CMemoryPool()
195 {
196 //DeleteCriticalSection(&m_critsec);
197 }
198
Alloc()199 CBuffer* CMemoryPool::Alloc()
200 {
201 CBuffer* pBuffer = NULL;
202 unsigned int dwFreeCount;
203
204 Enter();
205 dwFreeCount = m_freePool.Count();
206 if(m_bAutoGrow && dwFreeCount == 0)
207 {
208 Resize(m_dwCount * 2);
209 dwFreeCount = m_freePool.Count();
210 }
211 if(dwFreeCount > 0)
212 {
213
214 pBuffer = m_freePool.RemoveTail();
215 m_usedPool.AddHead(pBuffer);
216 }
217 Leave();
218
219 return pBuffer;
220 }
221
Free(CBuffer * pBuffer)222 void CMemoryPool::Free(CBuffer* pBuffer)
223 {
224 Enter();
225 m_usedPool.Remove(pBuffer);
226 m_freePool.AddHead(pBuffer);
227 Leave();
228 }
229
GetTotalBuffers()230 unsigned int CMemoryPool::GetTotalBuffers()
231 {
232 return m_dwCount;
233 }
234
GetUsedBuffers()235 unsigned int CMemoryPool::GetUsedBuffers()
236 {
237 return m_usedPool.Count();
238 }
239
GetFreeBuffers()240 unsigned int CMemoryPool::GetFreeBuffers()
241 {
242 return m_freePool.Count();
243 }
244
GetBufferSize()245 unsigned int CMemoryPool::GetBufferSize()
246 {
247 return m_dwBufferSize;
248 }
249
Resize(unsigned long dwNewCount)250 bool CMemoryPool::Resize(unsigned long dwNewCount)
251 {
252 bool bResult = true;
253
254
255 Enter();
256 if(dwNewCount > m_dwCount)
257 {
258 while(m_dwCount < dwNewCount)
259 {
260 m_dwCount++;
261 CBuffer* pNewBuffer = new CBuffer(this);
262 m_freePool.AddHead(pNewBuffer);
263 }
264 }
265 else
266 {
267 if(m_dwCount - dwNewCount > m_freePool.Count())
268 {
269 bResult = false;
270 }
271 while(m_dwCount-- > dwNewCount)
272 {
273 delete m_freePool.RemoveTail();
274 }
275 }
276 Leave();
277 return bResult;
278 }
279
ResizeD(long iCountDiff)280 bool CMemoryPool::ResizeD(long iCountDiff)
281 {
282 return Resize(m_dwCount + iCountDiff);
283 }
284
IsAutoGrow()285 bool CMemoryPool::IsAutoGrow()
286 {
287 return m_bAutoGrow;
288 }
289