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

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


    #ifndef __MEMMAN__
    #define __MEMMAN__

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

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

        
    extern time_type    num_stream_out;

        
    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() 
    const
            
    {
                
    return available_size;
            }


            mem_inline 
    void print()
            
    {
                std::cout 
    << std::endl;
                std::cout 
    << "========== heap Statistics ==========" << std::endl;
                std::cout 
    << std::endl;

                std::cout 
    << std::endl;
                std::cout 
    << "=====================================" << std::endl;
                std::cout 
    << std::endl;
            }


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


            mem_inline 
    void print()
            
    {
                std::cout 
    << std::endl;
                std::cout 
    << "========== pool Statistics ==========" << std::endl;
                std::cout 
    << std::endl;

                std::cout 
    << std::endl;
                std::cout 
    << "=====================================" << std::endl;
                std::cout 
    << std::endl;
            }


        
    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:
                
    virtual void stream_in() = 0;

                
    virtual size_type stream_size() = 0;

                
    virtual void *stream_out() = 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 );
                }


                mem_inline time_type get_last_use_time() 
    const
                
    {
                    
    if( ptr )
                        
    return ptr->last_use_time;
                    
    else
                        
    return 0;
                }


                mem_inline 
    bool is_locked() const
                
    {
                    
    if( ptr )
                        
    return ptr->is_locked();
                    
    else
                        
    return false;
                }


                mem_inline size_type stream_size()
                
    {
                    
    if( ptr )
                        
    return ptr->stream_size();
                    
    else
                        
    return 0;
                }


                mem_inline 
    bool stream_out( void * & p )
                
    {
                    
    if( ptr )
                    
    {
                        p 
    = ptr->stream_out();

                        ptr
    ->node_ptr = NULL;

                        
    ++ num_stream_out;

                        
    return true;
                    }

                    
    else
                        
    return false;
                }


                mem_inline 
    void detach()
                
    {
                    
    if( prev )
                        prev
    ->next = next;
                    
    if( next )
                        next
    ->prev = prev;
                }


                mem_inline 
    void g_detach()
                
    {
                    
    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
    ->g_detach();
                        p
    ->~node();
                        node_pool.dealloc( p, 
    sizeof(node) );

                        p 
    = head.next;
                    }

                }


                mem_inline 
    void recycle( page *old )
                
    {
                    node    
    *= head.next;

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

                        p
    ->g_detach();
                        p
    ->~node();
                        node_pool.dealloc( p, 
    sizeof(node) );
                        
                        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() 
    const
                
    {
                    
    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() 
    const
                
    {
                    
    return size;
                }


            
    public:
                chunk                    
    *next;
                chunk                    
    *prev;
                size_type                size;
            }
    ;

        
    public:
            mem_inline cache()
            
    {
                current_time 
    = 0;
                pages 
    = NULL;
                chunks 
    = NULL;
                allocated 
    = 0;
                g_num_nodes 
    = 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
                        
    {
                            std::cout 
    << "fatal: failed to allocate memory!" << std::endl;
                            
    return NULL;
                        }

                    }

                }

                
    else
                
    {
                    allocate_page( size );

                    
    if( search_page( ptr, size, obj ) )
                        
    return ptr;
                    
    else
                    
    {
                        std::cout 
    << "fatal: failed to allocate memory!" << std::endl;
                        
    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->g_detach();
                    obj
    ->node_ptr->~node();
                    node_pool.dealloc( obj
    ->node_ptr, sizeof(node) );
                    obj
    ->node_ptr = NULL;

                    
    -- g_num_nodes;
                }


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


            mem_inline 
    void print()
            
    {
                std::cout 
    << std::endl;
                std::cout 
    << "========== cache Statistics ==========" << std::endl;
                std::cout 
    << std::endl;

                std::cout 
    << std::endl;
                std::cout 
    << "======================================" << std::endl;
                std::cout 
    << std::endl;
            }


        
    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_num_nodes 
    = 0;
            }


            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;
                        
    ++ g_num_nodes;
                        
                        
    return true;
                    }


                    p 
    = p->next;
                }


                
    return false;
            }


            mem_inline 
    bool search_entry( void * & ptr, size_type size, entry *obj )
            
    {
                node    
    *old = NULL;
                node    
    *= g_head.g_next;

                
    while( p )
                
    {
                    
    if!p->is_locked() &&
                        p
    ->stream_size() >= size )
                    
    {
                        
    if( old )
                        
    {
                            
    if*p->ptr < *old->ptr )
                                old 
    = p;
                        }

                        
    else
                            old 
    = p;
                    }


                    p 
    = p->g_next;
                }


                
    if( old && old->stream_out( ptr ) )
                
    {
                    old
    ->ptr = obj;

                    obj
    ->node_ptr = old;
                        
                    
    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 != 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;
            size_type                        g_num_nodes;
            page                            
    *pages;
            chunk                            
    *chunks;
            
    static pool< ALLOC >            node_pool;
        }
    ;

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

                upl 
    = NULL;
                apl 
    = NULL;

                num_stream_out 
    = 0;
            }


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

                num_stream_out 
    = 0;
            }


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


            mem_inline 
    void print()
            
    {
                std::cout 
    << std::endl;
                std::cout 
    << "********** MemMan Statistics **********" << std::endl;
                std::cout 
    << std::endl;

                
    if( m_heap )
                    m_heap
    ->print();

                
    if( upl )
                    upl
    ->print();

                
    if( apl )
                    apl
    ->print();

                cache
    < mem::man::allocator >::entry::pl.print();

                cache
    < mem::man::aligned_allocator >::entry::pl.print();

                std::cout 
    << std::endl;
                std::cout 
    << "number of stream_out: " << num_stream_out << std::endl;
                std::cout 
    << std::endl;

                std::cout 
    << std::endl;
                std::cout 
    << "***************************************" << std::endl;
                std::cout 
    << std::endl;
            }


        
    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() 
    const
                
    {
                    
    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() 
    const
                
    {
                    
    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__


     

    /**************************************************
     *
     * 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::cache< mem::man::allocator >::node_pool;
    mem::pool
    < mem::man::aligned_allocator >    mem::cache< mem::man::aligned_allocator >::node_pool;
    mem::time_type                                mem::num_stream_out;
    mem::cache
    < mem::man::allocator >            mem::cache< mem::man::allocator >::entry::pl;
    mem::cache
    < mem::man::aligned_allocator >    mem::cache< mem::man::aligned_allocator >::entry::pl;


    #endif    //    __MEMMAN_DEF__
  • 相关阅读:
    BZOJ 1911: [Apio2010]特别行动队 斜率优化dp
    BZOJ 2751: [HAOI2012]容易题(easy) 数学
    Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B. Guess the Permutation 水题
    Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) A. Slime Combining 水题
    BZOJ 2768: [JLOI2010]冠军调查 最小割
    BZOJ 1497: [NOI2006]最大获利 最小割
    Codeforces Round #140 (Div. 1) D. The table 构造
    ICPC-CAMP day1 D.Around the world
    Codeforces Round #340 (Div. 2) E. XOR and Favorite Number 莫队算法
    BZOJ 2038 [2009国家集训队]小Z的袜子 莫队
  • 原文地址:https://www.cnblogs.com/len3d/p/992295.html
Copyright © 2011-2022 走看看