MemMan beta 3
/**/
/************************************************** * * MemMan 3.0.0.0 beta * * Copyright (C) 2007 - 2008 by Len3d * All rights reserved. * *************************************************/
#ifndef __MEMMAN__
#define
__MEMMAN__
#include
<
malloc.h
>
#pragma pack(push,
1
)
namespace
mem
{ #define mem_inline __forceinline #define mem_pool_pad 16 #define mem_page_pad 48 #define mem_page_size ( 1 << 18 ) #define mem_align_size 16 #define mem_align __declspec( align( mem_align_size ) ) typedef unsigned int prior_type; typedef unsigned long time_type; typedef unsigned long size_type; typedef unsigned char byte; #define mem_max( a, b ) ( ( (a) > (b) ) ? (a) : (b) ) #define mem_min( a, b ) ( ( (a) < (b) ) ? (a) : (b) ) enum { ENTRY_PRIORITY = 0, }; class heap { public: mem_inline heap( size_type max_size ) { allocated_size = 0; available_size = max_size; } mem_inline ~heap() { } mem_inline void *alloc( size_type size ) { if( size == 0 ) return NULL; allocated_size += size; available_size -= size; return sys_alloc( size ); } mem_inline void dealloc( void *ptr, size_type size ) { if( ptr && size != 0 ) { sys_dealloc( ptr ); allocated_size -= size; available_size += size; } } mem_inline void *aligned_alloc( size_type size ) { if( size == 0 ) return NULL; allocated_size += size; available_size -= size; return sys_aligned_alloc( size ); } mem_inline void aligned_dealloc( void *ptr, size_type size ) { if( ptr && size != 0 ) { sys_aligned_dealloc( ptr ); allocated_size -= size; available_size += size; } } mem_inline size_type available() { return available_size; } private: mem_inline void *sys_alloc( size_type size ) { return malloc( size ); } mem_inline void sys_dealloc( void *ptr ) { free( ptr ); } mem_inline void *sys_aligned_alloc( size_type size ) { return _aligned_malloc( size, mem_align_size ); } mem_inline void sys_aligned_dealloc( void *ptr ) { _aligned_free( ptr ); } private: size_type allocated_size, available_size; }; template < typename ALLOC > class pool { private: class page { public: mem_inline page( size_type _size, page *old ) { base = get_base(); _next = old; size = _size; } mem_inline byte *get_base() { return ( (byte *) this + sizeof(page) ); } mem_inline size_type get_size() { return static_cast<size_type>( base - get_base() + size ); } mem_inline size_type available() { return size; } mem_inline void *alloc( size_type _size ) { byte *ptr = base; base += _size; size -= _size; return ptr; } mem_inline page *next() { return _next; } private: mem_align union { struct { byte *base; page *_next; size_type size; }; byte pad[mem_pool_pad]; }; }; class chunk { public: mem_inline chunk( size_type _size, chunk *old ) { next = old; size = _size; } mem_inline size_type available() { return size; } public: chunk *next; size_type size; }; public: mem_inline pool() { pages = NULL; chunks = NULL; allocated = 0; } mem_inline ~pool() { destory(); } mem_inline void destory() { page *p; while( ( p = pages ) != NULL ) { pages = p->next(); al.dealloc( p, p->get_size() ); } pages = NULL; chunks = NULL; } mem_inline bool search_chunk( void * & ptr, size_type size ) { if( chunks && ( size <= chunks->available() ) ) { ptr = (void *) chunks; chunks = chunks->next; return true; } else return false; } mem_inline bool search_page( void * & ptr, size_type size ) { if( pages && ( size <= pages->available() ) ) { ptr = pages->alloc( size ); return true; } else return false; } mem_inline void allocate_page( size_type size ) { size_type asize = mem_max( size, mem_page_size ); pages = new (al.alloc( sizeof(page) + asize )) page( asize, pages ); } mem_inline void *alloc( size_type size ) { void *ptr; ++ allocated; if( search_chunk( ptr, size ) ) return ptr; else if( search_page( ptr, size ) ) return ptr; else { allocate_page( size ); if( search_page( ptr, size ) ) return ptr; else return NULL; } } mem_inline void dealloc( void *ptr, size_type size ) { -- allocated; if( size >= sizeof(chunk) ) chunks = new (ptr) chunk( size, chunks ); if( allocated == 0 ) destory(); } private: page *pages; chunk *chunks; size_type allocated; ALLOC al; }; template < typename ALLOC > class cache { public: class node; class entry { public: mem_inline entry() { priority = ENTRY_PRIORITY; last_use_time = pl.get_current_time(); locked = false; node_ptr = NULL; } mem_inline virtual ~entry() { } mem_inline void *alloc( size_type size ) { return pl.alloc( size, this ); } mem_inline void dealloc( void *ptr, size_type size ) { pl.dealloc( ptr, size, this ); } mem_inline void stream_begin() { locked = true; stream_in(); last_use_time = pl.get_current_time(); } mem_inline void stream_end() { locked = false; } mem_inline bool is_locked() { return locked; } mem_inline bool operator < ( const entry & right ) const { if( priority == right.priority ) return ( last_use_time < right.last_use_time ); else return ( priority < right.priority ); } public:#ifdef _DEBUG virtual void stream_in() = 0;#endif virtual bool stream_out( void * & ptr, size_type size ) = 0; public: static cache< ALLOC > pl; prior_type priority; time_type last_use_time; bool locked; node *node_ptr; }; class node { public: mem_inline node( entry *obj, node *old, node *g_old, node *phead, node *g_phead ) { ptr = obj; obj->node_ptr = this; next = old; prev = phead; g_next = g_old; g_prev = g_phead; if( next ) next->prev = this; if( prev ) prev->next = this; if( g_next ) g_next->g_prev = this; if( g_prev ) g_prev->g_next = this; } mem_inline node() { ptr = NULL; next = NULL; prev = NULL; g_next = NULL; g_prev = NULL; } mem_inline ~node() { void *p = NULL; stream_out( p, 0 ); } mem_inline time_type get_last_use_time() { if( ptr ) return ptr->last_use_time; else return 0; } mem_inline bool is_locked() { if( ptr ) return ptr->is_locked(); else return false; } mem_inline bool stream_out( void * & p, size_type size ) { if( ptr ) { bool bret = ptr->stream_out( p, size ); if( bret ) ptr->node_ptr = NULL; return bret; } else return false; } mem_inline void detach() { if( prev ) prev->next = next; if( next ) next->prev = prev; if( g_prev ) g_prev->g_next = g_next; if( g_next ) g_next->g_prev = g_prev; } public: entry *ptr; node *next, *prev; node *g_next, *g_prev; }; class page { public: mem_inline page( size_type _size, page *old ) { size = _size; base = get_base(); next = old; prev = NULL; if( next ) next->prev = this; num_nodes = 0; } mem_inline ~page() { node *p = head.next; while( p ) { head.next = p->next; p->detach(); delete p; p = head.next; } } mem_inline void recycle( page *old ) { node *p = head.next; while( p ) { head.next = p->next; p->detach(); delete p; p = head.next; } head.next = NULL; size = get_size(); base = get_base(); next = old; prev = NULL; if( next ) next->prev = this; num_nodes = 0; } mem_inline byte *get_base() { return (byte *) this + sizeof(page); } mem_inline size_type get_size() { return static_cast<size_type>( base - get_base() + size ); } mem_inline size_type available() { return size; } mem_inline void *alloc( size_type req_size ) { void *ptr = (void *) base; base += req_size; size -= req_size; return ptr; } mem_inline time_type priority() const { time_type last_use_time = 0; node *p = head.next; while( p ) { last_use_time += p->get_last_use_time(); p = p->next; } if( num_nodes != 0 ) last_use_time /= static_cast<time_type>( num_nodes ); return last_use_time; } mem_inline bool operator < ( const page & right ) const { return ( priority() < right.priority() ); } public: mem_align union { struct { byte *base; page *next; page *prev; size_type size; node head; size_type num_nodes; }; byte pad[mem_page_pad]; }; }; class chunk { public: mem_inline chunk( size_type _size, chunk *old ) { size = _size; next = old; prev = NULL; if( next ) next->prev = this; } mem_inline size_type available() { return size; } public: chunk *next; chunk *prev; size_type size; }; public: mem_inline cache() { current_time = 0; pages = NULL; chunks = NULL; allocated = 0; } mem_inline ~cache() { destory(); } mem_inline time_type get_current_time() { return ( ++ current_time ); } mem_inline void *alloc( size_type size, entry *obj ) { void *ptr = NULL; ++ allocated; obj->node_ptr = NULL; if( search_chunk( ptr, size ) ) return ptr; else if( search_page( ptr, size, obj ) ) return ptr; else if( (size + sizeof(page)) > al.available() ) { if( search_entry( ptr, size, obj ) ) return ptr; else { recycle_page( size ); if( search_page( ptr, size, obj ) ) return ptr; else return NULL; } } else { allocate_page( size ); if( search_page( ptr, size, obj ) ) return ptr; else return NULL; } } mem_inline void dealloc( void *ptr, size_type size, entry *obj ) { -- allocated; if( obj->node_ptr ) { obj->node_ptr->detach(); obj->node_ptr->~node(); node_pool.dealloc( obj->node_ptr, sizeof(node) ); obj->node_ptr = NULL; } if( size >= sizeof(chunk) ) chunks = new (ptr) chunk( size, chunks ); if( allocated == 0 ) destory(); } private: mem_inline void destory() { page *p = pages; while( p ) { pages = p->next; p->~page(); al.dealloc( p, p->get_size() ); p = pages; } chunks = NULL; } mem_inline bool search_chunk( void * & ptr, size_type size ) { chunk *p = chunks; while( p ) { if( size <= p->available() ) { ptr = (void *) p; if( p->prev ) p->prev->next = p->next; if( p->next ) p->next->prev = p->prev; return true; } p = p->next; } return false; } mem_inline bool search_page( void * & ptr, size_type size, entry *obj ) { page *p = pages; while( p ) { if( size <= p->available() ) { ptr = p->alloc( size ); new (node_pool.alloc( sizeof(node) )) node( obj, p->head.next, g_head.g_next, &p->head, &g_head ); ++ p->num_nodes; return true; } p = p->next; } return false; } mem_inline node *node_sort( node *p ) { return p; } mem_inline bool search_entry( void * & ptr, size_type size, entry *obj ) { g_head.g_next = node_sort( g_head.g_next ); node *p = g_head.g_next; while( p ) { if( !p->is_locked() && p->stream_out( ptr, size ) ) { p->ptr = obj; obj->node_ptr = p; return true; } p = p->g_next; } return false; } mem_inline void recycle_page( size_type size ) { if( pages ) { page *p, *old; old = pages; p = pages->next; while( p ) { if( *p < *old ) old = p; p = p->next; } if( old != pages ) { if( old->prev ) old->prev->next = old->next; if( old->next ) old->next->prev = old->prev; old->recycle( pages ); pages = old; } } } mem_inline void allocate_page( size_type size ) { size_type asize = mem_min( mem_max( sizeof(page) + size, mem_page_size ), al.available() ); pages = new (al.alloc( asize )) page( asize - sizeof(page), pages ); } private: time_type current_time; time_type allocated; ALLOC al; node g_head; page *pages; chunk *chunks; pool< ALLOC > node_pool; }; class man { public: mem_inline man() { m_heap = NULL; upl = NULL; apl = NULL; } mem_inline ~man() { if( apl ) delete apl; if( upl ) delete upl; if( m_heap ) delete m_heap; } mem_inline void begin( size_type heap_size ) { m_heap = new heap( heap_size ); upl = new pool< allocator >; apl = new pool< aligned_allocator >; } mem_inline void end() { delete apl; apl = NULL; delete upl; upl = NULL; delete m_heap; m_heap = NULL; } mem_inline void *alloc( size_type size ) { return upl->alloc( size ); } mem_inline void dealloc( void *ptr, size_type size ) { return upl->dealloc( ptr, size ); } mem_inline void *aligned_alloc( size_type size ) { return apl->alloc( size ); } mem_inline void aligned_dealloc( void *ptr, size_type size ) { return apl->dealloc( ptr, size ); } public: static heap *m_heap; public: class allocator { public: mem_inline void *alloc( size_type size ) { return m_heap->alloc( size ); } mem_inline void dealloc( void *ptr, size_type size ) { m_heap->dealloc( ptr, size ); } mem_inline size_type available() { return m_heap->available(); } }; class aligned_allocator { public: mem_inline void *alloc( size_type size ) { return m_heap->aligned_alloc( size ); } mem_inline void dealloc( void *ptr, size_type size ) { m_heap->aligned_dealloc( ptr, size ); } mem_inline size_type available() { return m_heap->available(); } }; public: pool< allocator > *upl; pool< aligned_allocator > *apl; }; typedef cache< man::allocator >::entry resource; typedef cache< man::aligned_allocator >::entry aligned_resource;}
//
namespace mem
extern
mem::man memman;#pragma pack(pop)
#endif
//
__MEMMAN__
posted on
2007-12-11 15:31
Len3d 阅读(
...) 评论(
)
编辑
收藏
转载于:https://www.cnblogs.com/len3d/archive/2007/12/11/990867.html
转载请注明原文地址: https://win8.8miu.com/read-29488.html