• 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__
  • 相关阅读:
    Codeforces Round #564(div2)
    714
    1471
    UVa 11134
    UVa 1152 -4 Values whose Sum is 0—[哈希表实现]
    UVa 1374
    UVA 1343
    UVa 12325
    Yet Another Number Sequence——[矩阵快速幂]
    River Hopscotch-[二分查找、贪心]
  • 原文地址:https://www.cnblogs.com/len3d/p/988562.html
Copyright © 2020-2023  润新知