zoukankan      html  css  js  c++  java
  • MemMan 3 beta

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


    #ifndef __MEM_MAN__
    #define __MEM_MAN__

    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    <malloc.h>

    #pragma pack(push,
    1)

    namespace mem {

        
    #define mem_inline        __forceinline

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

        
    extern heap        *g_heap;

        
    class allocator {
        
    public:
            mem_inline 
    void *alloc( size_type size )
            
    {
                
    return g_heap->alloc( size );
            }


            mem_inline 
    void dealloc( void *ptr, size_type size )
            
    {
                g_heap
    ->dealloc( ptr, size );
            }


            mem_inline size_type available()
            
    {
                
    return g_heap->available();
            }

        }
    ;

        
    class aligned_allocator {
        
    public:
            mem_inline 
    void *alloc( size_type size )
            
    {
                
    return g_heap->aligned_alloc( size );
            }


            mem_inline 
    void dealloc( void *ptr, size_type size )
            
    {
                g_heap
    ->aligned_dealloc( ptr, size );
            }


            mem_inline size_type available()
            
    {
                
    return g_heap->available();
            }

        }
    ;

        template 
    < typename ALLOC = allocator > class pool;

        template 
    < typename ALLOC = allocator >
        
    class entry {
        
    public:
            mem_inline entry()
            
    {
                priority 
    = ENTRY_PRIORITY;
                last_use_time 
    = pl.get_current_time();
                locked 
    = false;
            }

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

        template 
    < typename ALLOC >
        mem_inline 
    bool compare_entry( const entry< ALLOC > *left, const entry< ALLOC > *right )
        
    {
            
    return ( *left < *right );
        }


        template 
    < typename ALLOC >
        
    class pool {
        
    private:
            
    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;
                }


                mem_inline 
    ~page()
                
    {
                }


                mem_inline 
    void recycle( page *old )
                
    {
                    
    void    *ptr = NULL;

                    
    for( std::vector< entry< ALLOC > * >::iterator i = ents.begin();
                            i 
    != ents.end(); ++i )
                    
    {
                        (
    *i)->stream_out( ptr, 0 );
                    }


                    ents.clear();

                    size 
    = get_size();
                    
    base = get_base();
                    next 
    = old;
                    prev 
    = NULL;
                    
    if( next )
                        next
    ->prev = this;
                }


                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, entry< ALLOC > *obj )
                
    {
                    
    void    *ptr = (void *base;

                    
    base += req_size;
                    size 
    -= req_size;

                    ents.push_back( obj );
                
                    
    return ptr;
                }


                mem_inline time_type priority() 
    const
                
    {
                    time_type    last_use_time 
    = 0;

                    
    for( std::vector< entry< ALLOC > * >::const_iterator i = ents.begin();
                            i 
    != ents.end(); ++i )
                    
    {
                        last_use_time 
    += (*i)->last_use_time;
                    }


                    last_use_time 
    /= static_cast<time_type>( ents.size() );

                    
    return last_use_time;
                }


                mem_inline 
    bool operator < ( const page & right ) const
                
    {
                    
    return ( priority() < right.priority() );
                }


            
    public:
                mem_align 
    struct {
                    
    byte                            *base;
                    page                            
    *next;
                    page                            
    *prev;
                    size_type                        size;
                    std::vector
    < entry< ALLOC > * >    ents;
                }
    ;
            }
    ;
            
            
    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< ALLOC > *obj )
            
    {
                
    void    *ptr = NULL;

                
    ++ allocated;

                
    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< ALLOC > *obj )
            
    {
                
    -- allocated;

                
    for( std::vector< entry< ALLOC > * >::iterator i = g_ents.begin();
                        i 
    != g_ents.end(); ++i )
                
    {
                    
    if( obj == *i )
                    
    {
                        g_ents.erase( i );
                        
    break;
                    }

                }


                
    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;

                g_ents.clear();
            }


            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< ALLOC > *obj )
            
    {
                page    
    *= pages;
                
                
    while( p )
                
    {
                    
    if( size <= p->available() )
                    
    {
                        ptr 
    = p->alloc( size, obj );

                        g_ents.push_back( obj );
                        
                        
    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_entry( void * & ptr, size_type size, entry< ALLOC > *obj )
            
    {
                std::sort( g_ents.begin(), g_ents.end(), compare_entry
    < ALLOC > );

                
    for( std::vector< entry< ALLOC > * >::iterator i = g_ents.begin();
                        i 
    != g_ents.end(); ++i )
                
    {
                    
    if!(*i)->is_locked() && (*i)->stream_out( ptr, size ) )
                    
    {
                        
    *= obj;
                        
    return true;
                    }

                }


                
    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;
            std::vector
    < entry< ALLOC > * >    g_ents;
            page                            
    *pages;
            chunk                            
    *chunks;
        }
    ;

    }
        //    namespace mem


    #pragma pack(pop)


    #endif    //    __MEM_MAN__
  • 相关阅读:
    Atitit.ati orm的设计and架构总结 适用于java c# php版
    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
    Atitit. 软件设计 模式 变量 方法 命名最佳实践 vp820 attilax总结命名表大全
    Atitit. 软件设计 模式 变量 方法 命名最佳实践 vp820 attilax总结命名表大全
    Atitit 插件机制原理与设计微内核 c# java 的实现attilax总结
    Atitit 插件机制原理与设计微内核 c# java 的实现attilax总结
    atitit.基于  Commons CLI 的命令行原理与 开发
    atitit.基于  Commons CLI 的命令行原理与 开发
    atitit.js 与c# java交互html5化的原理与总结.doc
  • 原文地址:https://www.cnblogs.com/len3d/p/988562.html
Copyright © 2011-2022 走看看