len3d

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
/**************************************************
 *
 * 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_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 {
    
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 pool< 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( g_next )
                    g_next
->g_prev = this;
            }


            mem_inline node()
            
{
                ptr 
= NULL;
                next 
= NULL;
                prev 
= NULL;
                g_next 
= NULL;
                g_prev 
= NULL;
            }


            mem_inline 
~node()
            
{
                
void    *= 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    
*= head.next;

                
while( p )
                
{
                    head.next 
= p->next;

                    p
->detach();
                    delete p;

                    p 
= head.next;
                }

            }


            mem_inline 
void recycle( page *old )
            
{
                node    
*= 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    
*= head.next;

                
while( p )
                
{
                    last_use_time 
+= p->get_last_use_time();

                    p 
= p->next;
                }


                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 pool()
        
{
            current_time 
= 0;
            pages 
= NULL;
            chunks 
= NULL;
            allocated 
= 0;
        }


        mem_inline 
~pool()
        
{
            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();
                delete obj
->node_ptr;
                obj
->node_ptr = NULL;
            }


            
if( size >= sizeof(chunk) )
                chunks 
= new (ptr) chunk( size, chunks );
        
            
if( allocated == 0 )
                destory();
        }


    
private:
        mem_inline 
void destory()
        
{
            page    
*= 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    
*= 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    
*= pages;
            
            
while( p )
            
{
                
if( size <= p->available() )
                
{
                    ptr 
= p->alloc( size );

                    p
->head.next = g_head.next = new node( obj, p->head.next, g_head.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    
*= 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*< *old )
                        old 
= p;

                    p 
= p->next;
                }


                
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;
    }
;

    
class man {
    
public:
        mem_inline man()
        
{
            m_heap 
= NULL;
        }


        mem_inline 
~man()
        
{
            
if( m_heap )
                delete m_heap;
        }


        mem_inline 
void begin( size_type heap_size )
        
{
            
if( m_heap )
                end();

            m_heap 
= new heap( heap_size );
        }


        mem_inline 
void end()
        
{
            
if( m_heap )
            
{
                delete m_heap;
                m_heap 
= NULL;
            }

        }


    
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();
            }

        }
;
    }
;

    typedef pool
< man::allocator >::entry            resource;
    typedef pool
< man::aligned_allocator >::entry    aligned_resource;

}
    //    namespace mem

extern mem::man        memman;


#pragma pack(pop)


#endif    //    __MEMMAN__
/**************************************************
 *
 * MemMan 3.0.0.0 beta
 *
 * Copyright (C) 2007 - 2008 by Len3d
 * All rights reserved.
 *
 ************************************************
*/


#ifndef __MEMMAN_DEF__
#define __MEMMAN_DEF__


#include 
"memman3.h"

mem::man                                    memman;
mem::heap                                    
*mem::man::m_heap;
mem::pool
< mem::man::allocator >            mem::pool< mem::man::allocator >::entry::pl;
mem::pool
< mem::man::aligned_allocator >    mem::pool< mem::man::aligned_allocator >::entry::pl;


#endif    //    __MEMMAN_DEF__
posted on 2007-12-10 22:27  Len3d  阅读(213)  评论(1编辑  收藏  举报