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