![](/Images/OutliningIndicators/ExpandedBlockStart.gif) /**//**************************************************
*
* MemMan 3.0.0.0 beta
*
* Copyright (C) 2007 - 2008 by Len3d
* All rights reserved.
*
*************************************************/
![](/Images/OutliningIndicators/None.gif)
#ifndef __MEM_MAN__
#define __MEM_MAN__
![](/Images/OutliningIndicators/None.gif)
#include <vector>
#include <algorithm>
#include <malloc.h>
![](/Images/OutliningIndicators/None.gif)
#pragma pack(push,1)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif) namespace mem {
![](/Images/OutliningIndicators/InBlock.gif)
#define mem_inline __forceinline
![](/Images/OutliningIndicators/InBlock.gif)
#define mem_page_size ( 1 << 18 )
#define mem_align_size 16
#define mem_align __declspec( align( mem_align_size ) )
![](/Images/OutliningIndicators/InBlock.gif)
typedef unsigned int prior_type;
typedef unsigned long time_type;
typedef unsigned long size_type;
typedef unsigned char byte;
![](/Images/OutliningIndicators/InBlock.gif)
#define mem_max( a, b ) ( ( (a) > (b) ) ? (a) : (b) )
#define mem_min( a, b ) ( ( (a) < (b) ) ? (a) : (b) )
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) enum {
ENTRY_PRIORITY = 0,
};
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class heap {
public:
mem_inline heap( size_type max_size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
allocated_size = 0;
available_size = max_size;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline ~heap()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( size == 0 )
return NULL;
![](/Images/OutliningIndicators/InBlock.gif)
allocated_size += size;
available_size -= size;
![](/Images/OutliningIndicators/InBlock.gif)
return sys_alloc( size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void dealloc( void *ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( ptr && size != 0 )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
sys_dealloc( ptr );
![](/Images/OutliningIndicators/InBlock.gif)
allocated_size -= size;
available_size += size;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *aligned_alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( size == 0 )
return NULL;
![](/Images/OutliningIndicators/InBlock.gif)
allocated_size += size;
available_size -= size;
![](/Images/OutliningIndicators/InBlock.gif)
return sys_aligned_alloc( size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void aligned_dealloc( void *ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( ptr && size != 0 )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
sys_aligned_dealloc( ptr );
![](/Images/OutliningIndicators/InBlock.gif)
allocated_size -= size;
available_size += size;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type available()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return available_size;
}
![](/Images/OutliningIndicators/InBlock.gif)
private:
mem_inline void *sys_alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return malloc( size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void sys_dealloc( void *ptr )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
free( ptr );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *sys_aligned_alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return _aligned_malloc( size, mem_align_size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void sys_aligned_dealloc( void *ptr )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
_aligned_free( ptr );
}
![](/Images/OutliningIndicators/InBlock.gif)
private:
size_type allocated_size,
available_size;
};
![](/Images/OutliningIndicators/InBlock.gif)
extern heap *g_heap;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class allocator {
public:
mem_inline void *alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return g_heap->alloc( size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void dealloc( void *ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
g_heap->dealloc( ptr, size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type available()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return g_heap->available();
}
};
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class aligned_allocator {
public:
mem_inline void *alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return g_heap->aligned_alloc( size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void dealloc( void *ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
g_heap->aligned_dealloc( ptr, size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type available()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return g_heap->available();
}
};
![](/Images/OutliningIndicators/InBlock.gif)
template < typename ALLOC = allocator > class pool;
![](/Images/OutliningIndicators/InBlock.gif)
template < typename ALLOC = allocator >
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class entry {
public:
mem_inline entry()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
priority = ENTRY_PRIORITY;
last_use_time = pl.get_current_time();
locked = false;
}
mem_inline virtual ~entry()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *alloc( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return pl.alloc( size, this );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void dealloc( void *ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
pl.dealloc( ptr, size, this );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void stream_begin()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
locked = true;
stream_in();
last_use_time = pl.get_current_time();
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void stream_end()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
locked = false;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool is_locked()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return locked;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool operator < ( const entry< ALLOC > & right ) const
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( priority == right.priority )
return ( last_use_time < right.last_use_time );
else
return ( priority < right.priority );
}
![](/Images/OutliningIndicators/InBlock.gif)
public:
#ifdef _DEBUG
virtual void stream_in() = 0;
#endif
![](/Images/OutliningIndicators/InBlock.gif)
virtual bool stream_out( void * & ptr, size_type size ) = 0;
![](/Images/OutliningIndicators/InBlock.gif)
public:
static pool< ALLOC > pl;
prior_type priority;
time_type last_use_time;
bool locked;
};
![](/Images/OutliningIndicators/InBlock.gif)
template < typename ALLOC >
mem_inline bool compare_entry( const entry< ALLOC > *left, const entry< ALLOC > *right )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return ( *left < *right );
}
![](/Images/OutliningIndicators/InBlock.gif)
template < typename ALLOC >
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class pool {
private:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class page {
public:
mem_inline page( size_type _size, page *old )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
size = _size;
base = get_base();
next = old;
prev = NULL;
if( next )
next->prev = this;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline ~page()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void recycle( page *old )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
void *ptr = NULL;
![](/Images/OutliningIndicators/InBlock.gif)
for( std::vector< entry< ALLOC > * >::iterator i = ents.begin();
i != ents.end(); ++i )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
(*i)->stream_out( ptr, 0 );
}
![](/Images/OutliningIndicators/InBlock.gif)
ents.clear();
![](/Images/OutliningIndicators/InBlock.gif)
size = get_size();
base = get_base();
next = old;
prev = NULL;
if( next )
next->prev = this;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline byte *get_base()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return (byte *) this + sizeof(page);
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type get_size()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return static_cast<size_type>( base - get_base() + size );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type available()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return size;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *alloc( size_type req_size, entry< ALLOC > *obj )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
void *ptr = (void *) base;
![](/Images/OutliningIndicators/InBlock.gif)
base += req_size;
size -= req_size;
![](/Images/OutliningIndicators/InBlock.gif)
ents.push_back( obj );
return ptr;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline time_type priority() const
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
time_type last_use_time = 0;
![](/Images/OutliningIndicators/InBlock.gif)
for( std::vector< entry< ALLOC > * >::const_iterator i = ents.begin();
i != ents.end(); ++i )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
last_use_time += (*i)->last_use_time;
}
![](/Images/OutliningIndicators/InBlock.gif)
last_use_time /= static_cast<time_type>( ents.size() );
![](/Images/OutliningIndicators/InBlock.gif)
return last_use_time;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool operator < ( const page & right ) const
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return ( priority() < right.priority() );
}
![](/Images/OutliningIndicators/InBlock.gif)
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) mem_align struct {
byte *base;
page *next;
page *prev;
size_type size;
std::vector< entry< ALLOC > * > ents;
};
};
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) class chunk {
public:
mem_inline chunk( size_type _size, chunk *old )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
size = _size;
next = old;
prev = NULL;
if( next )
next->prev = this;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline size_type available()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return size;
}
![](/Images/OutliningIndicators/InBlock.gif)
public:
chunk *next;
chunk *prev;
size_type size;
};
![](/Images/OutliningIndicators/InBlock.gif)
public:
mem_inline pool()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
current_time = 0;
pages = NULL;
chunks = NULL;
allocated = 0;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline ~pool()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
destory();
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline time_type get_current_time()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
return ( ++ current_time );
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void *alloc( size_type size, entry< ALLOC > *obj )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
void *ptr = NULL;
![](/Images/OutliningIndicators/InBlock.gif)
++ allocated;
![](/Images/OutliningIndicators/InBlock.gif)
if( search_chunk( ptr, size ) )
return ptr;
else if( search_page( ptr, size, obj ) )
return ptr;
else if( (size + sizeof(page)) > al.available() )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( search_entry( ptr, size, obj ) )
return ptr;
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
recycle_page( size );
![](/Images/OutliningIndicators/InBlock.gif)
if( search_page( ptr, size, obj ) )
return ptr;
else
return NULL;
}
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
allocate_page( size );
![](/Images/OutliningIndicators/InBlock.gif)
if( search_page( ptr, size, obj ) )
return ptr;
else
return NULL;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void dealloc( void *ptr, size_type size, entry< ALLOC > *obj )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
-- allocated;
![](/Images/OutliningIndicators/InBlock.gif)
for( std::vector< entry< ALLOC > * >::iterator i = g_ents.begin();
i != g_ents.end(); ++i )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( obj == *i )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
g_ents.erase( i );
break;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
if( size >= sizeof(chunk) )
chunks = new (ptr) chunk( size, chunks );
if( allocated == 0 )
destory();
}
![](/Images/OutliningIndicators/InBlock.gif)
private:
mem_inline void destory()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
page *p = pages;
while( p )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
pages = p->next;
p->~page();
al.dealloc( p, p->get_size() );
p = pages;
}
![](/Images/OutliningIndicators/InBlock.gif)
chunks = NULL;
![](/Images/OutliningIndicators/InBlock.gif)
g_ents.clear();
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool search_chunk( void * & ptr, size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
chunk *p = chunks;
while( p )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( size <= p->available() )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
ptr = (void *) p;
if( p->prev )
p->prev->next = p->next;
if( p->next )
p->next->prev = p->prev;
return true;
}
![](/Images/OutliningIndicators/InBlock.gif)
p = p->next;
}
![](/Images/OutliningIndicators/InBlock.gif)
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool search_page( void * & ptr, size_type size, entry< ALLOC > *obj )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
page *p = pages;
while( p )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( size <= p->available() )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
ptr = p->alloc( size, obj );
![](/Images/OutliningIndicators/InBlock.gif)
g_ents.push_back( obj );
if( p->prev )
p->prev->next = p->next;
if( p->next )
p->next->prev = p->prev;
return true;
}
![](/Images/OutliningIndicators/InBlock.gif)
p = p->next;
}
![](/Images/OutliningIndicators/InBlock.gif)
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline bool search_entry( void * & ptr, size_type size, entry< ALLOC > *obj )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
std::sort( g_ents.begin(), g_ents.end(), compare_entry< ALLOC > );
![](/Images/OutliningIndicators/InBlock.gif)
for( std::vector< entry< ALLOC > * >::iterator i = g_ents.begin();
i != g_ents.end(); ++i )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( !(*i)->is_locked() && (*i)->stream_out( ptr, size ) )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
*i = obj;
return true;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void recycle_page( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( pages )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
page *p, *old;
![](/Images/OutliningIndicators/InBlock.gif)
old = pages;
p = pages->next;
![](/Images/OutliningIndicators/InBlock.gif)
while( p )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
if( *p < *old )
old = p;
![](/Images/OutliningIndicators/InBlock.gif)
p = p->next;
}
![](/Images/OutliningIndicators/InBlock.gif)
if( old->prev )
old->prev->next = old->next;
if( old->next )
old->next->prev = old->prev;
![](/Images/OutliningIndicators/InBlock.gif)
old->recycle( pages );
pages = old;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
mem_inline void allocate_page( size_type size )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
size_type asize = mem_min( mem_max( sizeof(page) + size, mem_page_size ), al.available() );
![](/Images/OutliningIndicators/InBlock.gif)
pages = new (al.alloc( asize )) page( asize - sizeof(page), pages );
}
![](/Images/OutliningIndicators/InBlock.gif)
private:
time_type current_time;
time_type allocated;
ALLOC al;
std::vector< entry< ALLOC > * > g_ents;
page *pages;
chunk *chunks;
};
![](/Images/OutliningIndicators/InBlock.gif)
} // namespace mem
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
#pragma pack(pop)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
#endif // __MEM_MAN__
|