MemMan beta 3

it2022-05-05  32

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    *= 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;                }                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    *= 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 );                    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    *= 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 != 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


最新回复(0)