17#ifndef AGX_MEMORYPOOL_H
18#define AGX_MEMORYPOOL_H
26namespace agx {
template <
typename T>
class MemoryPool; }
39 #define AGX_CHUNK_ALIGNMENT 128
40 #define AGX_CHUNK_GROW_FACTOR 1.5
48 BatchAllocator(
const char *name =
"BatchAllocator", uint32_t initialChunkSize = 64);
53 void *allocate(uint32_t numBytes);
54 void *allocate(uint32_t numBytes, uint32_t alignment);
55 void deallocate(
void *buffer);
94 MemoryPool(
const char *name =
"MemoryPool", uint32_t initialChunkSize = 64);
139 size_t size()
const {
return m_size; }
150 template <
typename T>
154 MemoryPoolOld(
size_t initialSize = 0,
size_t chunkSize = 64);
233 ChunkVector m_chunks;
237 size_t m_lastAllocatedNumElements;
238 float m_averageNumElements;
240 bool m_callConstructor;
241 size_t m_maxAllocationSize;
244 size_t m_elementIndex;
247 SizeVector m_sizeVector;
252 template <
typename T>
254 m_numUsed(0), m_chunkSize(chunkSize), m_numFlushes(0), m_lastAllocatedNumElements(0), m_averageNumElements(0),
255 m_flushCount(
std::numeric_limits<int>::
max() ), m_callConstructor(true),
256 m_maxAllocationSize(
std::numeric_limits<size_t>::
max() ),
m_capacity( 0 ), m_chunkIndex(0), m_elementIndex(0)
258 size_t numChunks = initialSize ? (initialSize / chunkSize) + 1 : 0;
259 for (
size_t i = 0; i < numChunks; i++)
263 template <
typename T>
269 template <
typename T>
275 template <
typename T>
281 template <
typename T>
284 return sizeof(T)*capacity();
288 template <
typename T>
294 template <
typename T>
297 m_callConstructor = flag;
300 template <
typename T>
303 m_maxAllocationSize = numBytes;
307 template <
typename T>
313 template <
typename T>
319 template <
typename T>
325 template <
typename T>
330 if ( m_numUsed > this->capacity() )
332 else if ( m_elementIndex >= m_sizeVector[ m_chunkIndex] )
339 T* element = m_chunks[m_chunkIndex]+m_elementIndex;
342 if (m_callConstructor)
343 ::new((
void *)element) T();
349 template <
typename T>
357 if (m_numUsed > this->capacity() || m_elementIndex >= m_sizeVector[ m_chunkIndex] )
361 T* element = m_chunks[m_chunkIndex]+m_elementIndex;
363 if (m_callConstructor)
364 ::new((
void *)element) T(initializer);
370 template <
typename T>
374 while (!m_chunks.empty())
381 m_lastAllocatedNumElements=0;
385 template <
typename T>
389 T* ptr =
static_cast<T*
>( allocateBytes(
sizeof(T) * m_chunkSize ) );
392 for (
size_t i=0; i < m_chunkSize; ++i)
393 ::new( (
void*) &ptr[i]) T();
396 m_chunks.push_back(ptr);
397 m_sizeVector.push_back( m_chunkSize );
399 m_chunkIndex = m_chunks.size()-1;
403 template <
typename T>
404 void MemoryPoolOld<T>::deleteChunk()
406 T* ptr = m_chunks.back();
408 for (
size_t i=0; i < m_sizeVector.back(); ++i)
411 deallocateBytes( ptr );
416 m_sizeVector.pop_back();
419 m_chunkIndex = m_chunks.size();
422 m_chunkIndex = m_chunks.size()-1;
427 template <
typename T>
431 m_lastAllocatedNumElements = m_numUsed;
432 m_averageNumElements = m_averageNumElements*0.3f + 0.7f*m_lastAllocatedNumElements;
440 if (m_flushCount > 0 && (
int)m_numFlushes > m_flushCount)
444 template <
typename T>
448 if (!m_numFlushes || !m_chunks.size())
453 size_t endIdx=m_sizeVector.size()-1;
455 for(
size_t i=0; i < m_sizeVector.size(); i++)
457 sum += m_sizeVector[i];
458 if (sum >= m_averageNumElements) {
464 size_t n=m_chunks.size();
465 for(
size_t i=n-1; i > endIdx; i--)
468 m_sizeVector.resize( m_chunks.size() );
552 template <
typename T>
557 size_t warningHack = 0;
559 agxAssert(
sizeof(
void*) <= (
sizeof(T)+warningHack) );
562 template <
typename T>
570 template <
typename T>
574 if ( m_freeHead != 0 )
577 m_freeHead = (T*) ( *((
void**)( m_freeHead )) );
584 template <
typename T>
587 void *element = this->allocate();
588 return ::new(element) T();
592 template <
typename T>
597 *((
void**)element) = m_freeHead;
598 m_freeHead = element;
602 template <
typename T>
606 this->deallocate(element);
609 template <
typename T>
612 this->deallocate(
static_cast<T *
>(ptr));
615 template <
typename T>
620 if ( this->m_freeHead )
629 chunkSizes.
push_back( chunkSizes.
back() + ((c->end - c->buffer) /
sizeof(T)) );
633 bitmap = (
char *)this->allocateBytes( chunkSizes.
back() );
634 memset( bitmap, 0, chunkSizes.
back() );
637 for (
void* l = this->m_freeHead; l != 0; l = *((
void**)l) )
642 while ( tmp && !( tmp->
buffer <= l && l <= tmp->head ) )
651 bitmap[ chunkSizes[idx] + ((
char*)l - tmp->
buffer) /
sizeof(T) ] = 1;
660 size_t end = (tmp->head - tmp->buffer) /
sizeof(T);
661 T* buff =
reinterpret_cast<T*
>(tmp->buffer);
663 for (
size_t e = 0; e <
end; ++e)
664 if ( !bitmap[ chunkSizes[idx] + e] )
669 this->deallocateBytes( bitmap );
681 T* element =
reinterpret_cast<T *
>(c->
buffer);
682 while ( (
char *)element < c->
head )
691 this->m_freeHead = 0;
696 template <
typename T>
703 this->m_freeHead = 0;
virtual void deallocateVirtual(void *ptr)=0
virtual ~AbstractMemoryPool()
void deallocate(void *buffer)
void * allocate(uint32_t numBytes)
void createChunk(uint32_t size)
BatchAllocator(const char *name="BatchAllocator", uint32_t initialChunkSize=64)
BatchAllocator & operator=(const BatchAllocator &other)
BatchAllocator(const BatchAllocator &other)
@ SHRINK_BUFFER
Buffer is deallocated and replaced by an newly allocated empty buffer.
void setAutoGarbageCollect(int n)
Set the number of calls to flush which will trigger a call to garbageCollect.
void setChunkSize(size_t size)
Set the new size of the chunk.
void garbageCollect()
Free memory not in use.
size_t getChunkSize() const
MemoryPoolOld(size_t initialSize=0, size_t chunkSize=64)
size_t capacity() const
\ return the total number of elements allocated
void flush()
Return all elements to container.
void clear()
Clear all memory allocated by this MemoryPoolOld.
void setEnableCallConstructor(bool flag)
Set to true if the constructor of the elements should be called BEFORE they are returned in getElemen...
int getAutoGarbageCollect() const
void setMaxAllocationSize(size_t numBytes)
Set the largest number of bytes a call to new will be.
virtual void deallocateVirtual(void *ptr)
void destroy(T *element)
Deallocates an element and calls its destructor.
void deallocate(T *element)
Deallocates one element, no destructor called.
T * allocate()
Allocates one element, no constructor called.
T * create()
Allocates an element and calls its default constructor.
void clear()
Clears the memory pool and runs the destructor on every allocated object.
void clearFast()
Clears the memory pool without calling destructors.
virtual ~MemoryPool()
Destructor.
MemoryPool(const char *name="MemoryPool", uint32_t initialChunkSize=64)
Constructor.
void push_back(const T2 &value)
#define agxAssert1(expr, msg)
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
bool isPowerOfTwo(T value)
LinearProbingHashSetImplementation< KeyT, HashT >::iterator end(LinearProbingHashSetImplementation< KeyT, HashT > &set)
Vec3T< T > max(const Vec3T< T > &lhs, const Vec3T< T > &rhs)