2
// Copyright � 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.com
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Declares the CqMemoryPool class for providing managed memory allocation.
23
\author Paul C. Gregory (pgregory@aqsis.com)
26
//? Is .h included already?
27
#ifndef MEMORYPOOL_H_INCLUDED
29
#define MEMORYPOOL_H_INCLUDED 1
37
START_NAMESPACE( Aqsis )
40
#define MEMORYPOOL_DEFAULTBLOCKSIZE 512
42
//----------------------------------------------------------------------
43
/** \class CqMemoryPool
44
* Template class for memory pool allocation
47
template <class T, long S = MEMORYPOOL_DEFAULTBLOCKSIZE>
51
CqMemoryPool() : m_pHead( 0 ), m_pFirstBlock( 0 )
53
virtual ~CqMemoryPool()
55
// Delete any remaining objects.
56
// Note if this happens and anyone is pointing to the
57
// allocated objects, you're in trouble.
61
/** Allocate a block from the pool.
62
* \param size The requested size of the block, should be sizeof T, if not something is wrong.
63
* \return void* pointer to memory block.
65
void* Alloc( size_t size )
68
// send requests of the "wrong" size to ::operator new();
69
if ( size != sizeof( T ) )
70
return ::operator new( size );
72
T* p = m_pHead; // Point to the first free block.
74
// if p is valid, just move the list head to the
75
// next element in the free list
76
if ( p ) m_pHead = p->m_pNext;
79
// The free list is empty. Allocate a block of memory
80
// big enough hold S objects
81
char* p_newBlock = static_cast<char*>( ::operator new( S*sizeof( T ) + sizeof(char*) ) );
82
T* newBlock = reinterpret_cast<T*>( p_newBlock + sizeof(char*) );
84
// Either initialise, or continue the linked list of blocks.
85
if( m_pFirstBlock != NULL )
87
void* pLastBlock = m_pFirstBlock;
88
while( static_cast<void**>( pLastBlock )[0] != 0 )
89
pLastBlock = static_cast<void**>( pLastBlock )[0];
90
static_cast<void**>( pLastBlock )[0] = p_newBlock;
91
reinterpret_cast<void**>( p_newBlock )[0] = 0;
95
reinterpret_cast<void**>( p_newBlock )[0] = 0;
96
m_pFirstBlock = p_newBlock;
99
// form a new free list by linking the memory chunks
100
// together; skip the zeroth element, because you'll
101
// return that to the caller of operator new
102
for ( int i = 1; i < S - 1; ++i )
103
newBlock[ i ].m_pNext = &newBlock[ i + 1 ];
105
// terminate the linked list with a null pointer
106
newBlock[ S - 1 ].m_pNext = 0;
108
// set p to front of list, headOfFreeList to
109
// chunk immediately following
111
m_pHead = &newBlock[ 1 ];
116
/** Deallocate a block from the pool.
117
* \param p Pointer to the block, should be in a valid pool, if not something is wrong.
118
* \param size The requested size of the block, should be sizeof T, if not something is wrong.
120
void DeAlloc( void* p, size_t size )
122
if ( p == 0 ) return ;
124
if ( size != sizeof( T ) )
126
::operator delete( p );
130
T *carcass = static_cast<T*>( p );
132
carcass->m_pNext = m_pHead;
136
/** Flush the pool block allocations.
140
void* p_Block = m_pFirstBlock;
143
void* p_nextBlock = static_cast<void**>( p_Block )[0];
145
p_Block = p_nextBlock;
152
T* m_pHead; ///< Pointer to the first free block in the pool.
158
//----------------------------------------------------------------------
159
/** \class CqPoolable
160
* Tamplate class to add the ability for a derived class to use a memory pool.
163
template <class T, long S = MEMORYPOOL_DEFAULTBLOCKSIZE>
167
CqPoolable() : m_pNext( 0 )
172
/** Overridden operator new to allocate micropolys from a pool.
174
void* operator new( size_t size )
176
return( m_thePool.Alloc( size ) );
179
/** Overridden operator delete to allocate micropolys from a pool.
181
void operator delete( void* p )
183
m_thePool.DeAlloc( p, sizeof( T ) );
186
T* m_pNext; ///< Pointer to the next object.
188
static CqMemoryPool<T, S> m_thePool; ///< Static pool to allocated micropolys from.
189
static void Flush() { m_thePool.Flush(); }
194
//-----------------------------------------------------------------------
195
/** Define the static memory pool for a poolable class.
198
#define DEFINE_STATIC_MEMORYPOOL(A, S) CqMemoryPool<A, S> CqPoolable<A, S>::m_thePool
201
//-----------------------------------------------------------------------
203
END_NAMESPACE( Aqsis )
205
//} // End of #ifdef MEMORYPOOL_H_INCLUDED