MemMan 1.0.0.0 Released!

it2022-05-05  33

MemMan 1.0.0.0 Released! /**/ /************************************************** * * MemMan 1.0.0.0 * * Copyright (C) 2007 - 2008 by Len3d * All rights reserved. * *************************************************/ #ifndef __MEM_MAN__ #define  __MEM_MAN__ #define  DEFAULT_MEMORY_ALIGN    16         //     default memory aligment set to this size #define  ALIGN_DEF                __declspec( align( DEFAULT_MEMORY_ALIGN ) ) #ifdef FORCEINLINE #undef  FORCEINLINE #endif #ifdef _DEBUG #define  FORCEINLINE        inline #else #define  FORCEINLINE        __forceinline #endif typedef  int     ( * FreeContentFunc)(  void   * object , UINT requested_size );     //     can't be member function of a class class  MemoryAllocator  {        //    memory allocator, takes charge of all system operations, also limits the usage of memoryprivate:    //    elements of the memory priority queue, keep track of all memory blocks    class MemoryQueueHeader {    public:        FORCEINLINE MemoryQueueHeader( UINT prior, void *obj, FreeContentFunc func, int al )        {            lchild = rchild = parent = NULL;            priority = prior;            object = obj;            free_func = func;            locked = TRUE;    //    we lock immediately after allocation            align = static_cast<short>( al );        }        //    we don't need a deconstructor for this class        FORCEINLINE void    lock()        {            locked = TRUE;        }        FORCEINLINE void    unlock()        {            locked = FALSE;        }        FORCEINLINE void    create_child( MemoryQueueHeader *key )        {            if( key->priority < priority )            {                if( lchild )                    lchild->create_child( key );                else                {                    lchild = key;                    lchild->parent = this;                }            }            else            {                if( rchild )                    rchild->create_child( key );                else                {                    rchild = key;                    rchild->parent = this;                }            }        }        FORCEINLINE bool    search_memory( UINT search_size, int search_align, void * & search_result,                                             void *obj, FreeContentFunc func )        {            if( lchild && lchild->search_memory( search_size, search_align, search_result, obj, func ) )                return true;            if( align == search_align && free_content( search_size ) )            {                search_result = get_memory();                object = obj;    //    update the attributes of the memory block                free_func = func;                return true;            }            if( rchild && rchild->search_memory( search_size, search_align, search_result, obj, func ) )                return true;            return false;        }        FORCEINLINE void    *get_memory()    //    the allocated memory block        {            return ((char *)this + sizeof(MemoryQueueHeader));        }        FORCEINLINE int        free_content( UINT requested_size )        {            if!locked && free_func && object )                return free_func( object, requested_size );            else                return 0;        }    public:        ALIGN_DEF struct {            MemoryQueueHeader    *lchild,    //    left child, right child and parent                                *rchild,                                *parent;            UINT                priority;    //    priority for sorting the memory blocks            void                *object;    //    the object for which the memory was allocated            FreeContentFunc        free_func;    //    function to free the content of the object for requested size,                                            //    memory blocks without this function will be restored to memory-mapped files.            short                locked;        //    this memory block was locked by a thread            short                align;        //    aligment of the allocated memory should match            int                    pad;        //    padded to 32 Byte aligned        };    };public:    MemoryAllocator( UINT max_size )    //    max allowed memory usage    {        allocated_size = 0;        available_size = max_size;        queue = NULL;        aligned_queue = NULL;    }    ~MemoryAllocator()    {        dealloc_header( queue );        dealloc_aligned_header( aligned_queue );    }    FORCEINLINE void    *alloc( UINT size, UINT priority,                                 void *object, FreeContentFunc free_func )    {        if( size == 0 )        {            return NULL;        }        else if( size > available_size )        //    searching has the complexity of O(N)        {            void    *ptr = NULL;            if( queue && queue->search_memory( size, 0, ptr, object, free_func ) )                return ptr;            else                return NULL;    //    the system has run out of memory        }        else    //    the complexity is O(logN)        {            allocated_size += ( size + sizeof(MemoryQueueHeader) );            available_size -= ( size + sizeof(MemoryQueueHeader) );            MemoryQueueHeader    *elem;            //    allocate a block            elem = new (sys_alloc( sizeof(MemoryQueueHeader) + size )) MemoryQueueHeader( priority, object, free_func, 0 );            if( queue )                queue->create_child( elem );    //    insert the node            else                queue = elem;    //    be the root            return elem->get_memory();        }    }    FORCEINLINE void    *aligned_alloc( UINT size, UINT priority,                                         void *object, FreeContentFunc free_func,                                         UINT align = DEFAULT_MEMORY_ALIGN )    {        if( size == 0 )        {            return NULL;        }        else if( size > available_size )        //    searching has the complexity of O(N)        {            void    *ptr = NULL;            if( aligned_queue && aligned_queue->search_memory( size, align, ptr, object, free_func ) )                return ptr;            else                return NULL;    //    the system has run out of memory        }        else    //    the complexity is O(logN)        {            allocated_size += ( size + sizeof(MemoryQueueHeader) );            available_size -= ( size + sizeof(MemoryQueueHeader) );            MemoryQueueHeader    *elem;            //    allocate an aligned block            elem = new (sys_aligned_alloc( sizeof(MemoryQueueHeader) + size, align )) MemoryQueueHeader( priority, object, free_func, align );            if( aligned_queue )                aligned_queue->create_child( elem );    //    insert the node            else                aligned_queue = elem;    //    be the root            return elem->get_memory();        }    }    //    a lock must be used before the object being deallocated, the complexity is O(1)        FORCEINLINE void    lockvoid *ptr )    {        if( ptr )        {            MemoryQueueHeader    *header = (MemoryQueueHeader *)((char *) ptr - sizeof(MemoryQueueHeader));            header->lock();        }    }    FORCEINLINE void    unlock( void *ptr )    {        if( ptr )        {            MemoryQueueHeader    *header = (MemoryQueueHeader *)((char *) ptr - sizeof(MemoryQueueHeader));            header->unlock();        }    }    //    deallocating has the complexity of O(logN)    FORCEINLINE void    dealloc( void *ptr )    {        if( ptr )        {            MemoryQueueHeader    *header, *node, *parent;            header = (MemoryQueueHeader *)((char *) ptr - sizeof(MemoryQueueHeader));            parent = header->parent;            if( header->lchild )    //    has left child            {                node = find_rightmost_child( header->lchild );                //    rebuild the link                if( node != header->lchild )                {                    if( node->parent )                        node->parent->rchild = NULL;    //    clear the link                    node->lchild = header->lchild;                    if( node->lchild )                        node->lchild->parent = node;                }                node->rchild = header->rchild;                if( node->rchild )                    node->rchild->parent = node;                node->parent = parent;                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = node;                    else if( parent->rchild == header )                        parent->rchild = node;                }                else    //    it's the root                {                    queue = node;                }            }            else if( header->rchild )    //    has right child            {                node = find_leftmost_child( header->rchild );                //    rebuild the link                if( node != header->rchild )                {                    if( node->parent )                        node->parent->lchild = NULL;    //    clear the link                    node->rchild = header->rchild;                    if( node->rchild )                        node->rchild->parent = node;                }                node->lchild = header->lchild;                if( node->lchild )                    node->lchild->parent = node;                node->parent = parent;                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = node;                    else if( parent->rchild == header )                        parent->rchild = node;                }                else    //    it's the root                {                    queue = node;                }            }            else    //    has no children            {                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = NULL;                    else if( parent->rchild == header )                        parent->rchild = NULL;                }                else    //    it's the root, clear it                {                    queue = NULL;                }            }            sys_dealloc( header );    //    deallocate the block        }    }    FORCEINLINE void    aligned_dealloc( void *ptr )    {        if( ptr )        {            MemoryQueueHeader    *header, *node, *parent;            header = (MemoryQueueHeader *)((char *) ptr - sizeof(MemoryQueueHeader));            parent = header->parent;            if( header->lchild )    //    has left child            {                node = find_rightmost_child( header->lchild );                //    rebuild the link                if( node != header->lchild )                {                    if( node->parent )                        node->parent->rchild = NULL;    //    clear the link                    node->lchild = header->lchild;                    if( node->lchild )                        node->lchild->parent = node;                }                node->rchild = header->rchild;                if( node->rchild )                    node->rchild->parent = node;                node->parent = parent;                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = node;                    else if( parent->rchild == header )                        parent->rchild = node;                }                else    //    it's the root                {                    queue = node;                }            }            else if( header->rchild )    //    has right child            {                node = find_leftmost_child( header->rchild );                //    rebuild the link                if( node != header->rchild )                {                    if( node->parent )                        node->parent->lchild = NULL;    //    clear the link                    node->rchild = header->rchild;                    if( node->rchild )                        node->rchild->parent = node;                }                node->lchild = header->lchild;                if( node->lchild )                    node->lchild->parent = node;                node->parent = parent;                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = node;                    else if( parent->rchild == header )                        parent->rchild = node;                }                else    //    it's the root                {                    queue = node;                }            }            else    //    has no children            {                if( parent )    //    has parent                {                    if( parent->lchild == header )                        parent->lchild = NULL;                    else if( parent->rchild == header )                        parent->rchild = NULL;                }                else    //    it's the root, clear it                {                    queue = NULL;                }            }            sys_aligned_dealloc( header );    //    deallocate the block        }    }private:    //    help functions    FORCEINLINE void    dealloc_header( MemoryQueueHeader *node )    {        if( node )        {            if( node->lchild )                dealloc_header( node->lchild );            if( node->rchild )                dealloc_header( node->rchild );            sys_dealloc( node );        }    }    FORCEINLINE void    dealloc_aligned_header( MemoryQueueHeader *node )    {        if( node )        {            if( node->lchild )                dealloc_aligned_header( node->lchild );            if( node->rchild )                dealloc_aligned_header( node->rchild );            sys_aligned_dealloc( node );        }    }    FORCEINLINE MemoryQueueHeader    *find_leftmost_child( MemoryQueueHeader *node )    {        if( node && node->lchild )            return find_leftmost_child( node->lchild );        else            return node;    }    FORCEINLINE MemoryQueueHeader    *find_rightmost_child( MemoryQueueHeader *node )    {        if( node && node->rchild )            return find_rightmost_child( node->rchild );        else            return node;    }private:    //    encapsulate system operations    FORCEINLINE void    *sys_alloc( UINT size )    {        return malloc( size );    }    FORCEINLINE void    *sys_aligned_alloc( UINT size, UINT align )    {        return _mm_malloc( size, align );    }    FORCEINLINE void    sys_dealloc( void *ptr )    {        free( ptr );    }    FORCEINLINE void    sys_aligned_dealloc( void *ptr )    {        _mm_free( ptr );    }private:    //    memory statistics    UINT                            allocated_size,                                     available_size;    //    implement priority queues to record all the allocations    MemoryQueueHeader                *queue;    MemoryQueueHeader                *aligned_queue;} ; #endif      //     __MEM_MAN__ posted on 2007-10-23 21:13 Len3d 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/len3d/archive/2007/10/23/935169.html


最新回复(0)