zoukankan      html  css  js  c++  java
  • C 工具库3:固定大小的 obj pool

    对大小固定的对象提供的对象池工具,当对内存分配的请求大小不固定时,使用其它的通用内存池.

    fix_obj_pool.h

    #ifndef _FIX_OBJ_POOL_H
    #define _FIX_OBJ_POOL_H


    struct fix_obj_pool;


    /*
    * obj_size:对象大小
    * default_size:默认对象池大小
    * align4:返回的对象地址是否需要对齐到4字节
    */
    extern struct fix_obj_pool *create_pool(unsigned int obj_size,int default_size,int align4);

    extern void destroy_pool(struct fix_obj_pool **pool);

    /*
    * 分配和回收
    */
    extern void *pool_alloc(struct fix_obj_pool*);

    extern void pool_dealloc(struct fix_obj_pool*,void*);

    extern unsigned int alignsize(unsigned int obj_size);

    extern unsigned int get_free_size(struct fix_obj_pool *pool);

    #endif

    fix_obj_pool.c

    #include "fix_obj_pool.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>

    static const char invalid_index = -1;
    static const unsigned int BLOCK_OBJ_SIZE = 128;
    struct block
    {
    char m_head;
    char m_tail;
    unsigned short m_freesize;
    struct block *m_next_block;
    unsigned int obj_size;//单个对象的大小
    union
    {
    char m_objs[1];
    unsigned int pad;
    };
    };

    inline void *block_get(struct block *_block,unsigned int index)
    {
    return (void*)&_block->m_objs[_block->obj_size * index];
    }

    inline int block_check(struct block *_block,void *obj)
    {
    if((char*)obj < _block->m_objs || (char*)obj >= (char*)block_get(_block,BLOCK_OBJ_SIZE))
    return 0;
    return 1;
    }


    void block_destroy(struct block **_block)
    {
    free(*_block);
    *_block = 0;
    }

    void block_init(struct block *_block,unsigned int obj_size)
    {
    _block->m_head = 0;
    _block->m_tail = BLOCK_OBJ_SIZE-1;
    _block->m_freesize = BLOCK_OBJ_SIZE;
    _block->obj_size = obj_size;
    int i;
    for(i = 0; i < BLOCK_OBJ_SIZE-1; ++i)
    {
    char *link = (char*)block_get(_block,i);
    *link = i+1;
    }
    char *link = (char*)block_get(_block,BLOCK_OBJ_SIZE-1);
    *link = invalid_index;
    _block->m_next_block = 0;
    }

    struct block *block_create(unsigned int obj_size)
    {
    struct block *_block = malloc(sizeof(*_block) + obj_size*BLOCK_OBJ_SIZE - sizeof(unsigned int));
    block_init(_block,obj_size);
    return _block;
    }

    void* block_alloc(struct block *_block)
    {
    if(_block->m_head == invalid_index)
    return 0;

    char *obj = (char*)block_get(_block,_block->m_head);
    _block->m_head = *obj;

    if(_block->m_head == invalid_index)
    _block->m_tail = invalid_index;
    *obj = invalid_index;
    --_block->m_freesize;
    return (void*)obj;
    }

    inline unsigned int block_get_obj_index(struct block *_block,void* obj)
    {
    unsigned int offset = (char*)obj - _block->m_objs;
    return offset/_block->obj_size;
    }

    void block_dealloc(struct block *_block,void* obj)
    {
    assert(block_check(_block,obj));
    char *link = (char *)obj;
    *link = invalid_index;
    char index = (char)block_get_obj_index(_block,obj);
    if(_block->m_tail == invalid_index)
    {
    _block->m_head = index;
    }
    else
    {
    *(char*)block_get(_block,_block->m_tail) = index;
    }
    _block->m_tail = index;
    ++_block->m_freesize;
    }

    inline unsigned char block_getfreesize(struct block *_block)
    {
    return _block->m_freesize;
    }

    inline void block_SetNextBlock(struct block *_block,struct block *next)
    {
    _block->m_next_block = next;
    }

    inline struct block *block_GetNext(struct block *_block)
    {
    return _block->m_next_block;
    }

    inline char *block_GetLastAddr(struct block *_block)
    {
    return (char*)block_get(_block,BLOCK_OBJ_SIZE-1);
    }

    struct chunk
    {
    struct block *m_head;
    struct block *m_tail;
    unsigned int m_freesize;
    unsigned int obj_size;
    unsigned int block_count;
    unsigned int block_size;
    struct chunk *m_next;
    struct block m_blocks[1];
    };

    inline struct block *chunk_get(struct chunk *_chunk,unsigned int index)
    {
    char *tmp = (char*)_chunk->m_blocks;
    return (struct block *)&tmp[_chunk->block_size*index];
    }

    void chunk_init(struct chunk *_chunk,unsigned int block_count,unsigned int block_size,unsigned int obj_size)
    {
    _chunk->m_freesize = block_count*BLOCK_OBJ_SIZE;
    _chunk->block_size = block_size;
    _chunk->block_count = block_count;
    unsigned int i;
    for(i = 0; i < block_count; ++i)
    {
    block_init(chunk_get(_chunk,i),obj_size);
    }
    for(i = 0; i < block_count-1; ++i)
    {
    block_SetNextBlock(chunk_get(_chunk,i),chunk_get(_chunk,i+1));
    }
    block_SetNextBlock(chunk_get(_chunk,block_count-1),0);
    _chunk->m_head = chunk_get(_chunk,0);
    _chunk->m_tail = chunk_get(_chunk,block_count-1);
    _chunk->m_next = 0;
    }

    struct chunk *chunk_create(unsigned int block_count,unsigned int obj_size)
    {
    unsigned int block_size = sizeof(struct block) + obj_size * BLOCK_OBJ_SIZE - sizeof(unsigned int);
    unsigned int chunk_size = block_size*block_count;
    struct chunk *_chunk = malloc(sizeof(*_chunk) + chunk_size - sizeof(_chunk->m_blocks));
    chunk_init(_chunk,block_count,block_size,obj_size);
    return _chunk;
    }

    void chunk_destroy(struct chunk **_chunk)
    {
    free(*_chunk);
    *_chunk = 0;
    }

    void* chunk_alloc(struct chunk *_chunk)
    {

    if(!_chunk->m_head)
    return 0;
    void *ret = block_alloc(_chunk->m_head);
    if(block_getfreesize(_chunk->m_head) == 0)
    {
    struct block *next = block_GetNext(_chunk->m_head);
    block_SetNextBlock(_chunk->m_head,0);
    if(!next)
    _chunk->m_head = _chunk->m_tail = 0;
    else
    _chunk->m_head = next;
    }
    --_chunk->m_freesize;
    return ret;
    }

    inline int chunk_check(struct chunk *_chunk,void *obj)
    {
    if((char*)obj < (char*)_chunk->m_blocks || (char*)obj >= (char*)chunk_get(_chunk,_chunk->block_count))
    return 0;
    return 1;
    }

    void chunk_dealloc(struct chunk *_chunk,void* obj)
    {
    assert(chunk_check(_chunk,obj));
    int index = (int)(((char*)obj - (char*)&_chunk->m_blocks[0])/_chunk->block_size);
    block_dealloc(chunk_get(_chunk,index),obj);

    if(block_getfreesize(chunk_get(_chunk,index)) == 1)
    {
    if(!_chunk->m_tail)
    {
    _chunk->m_head = chunk_get(_chunk,index);
    }
    else
    {
    block_SetNextBlock(_chunk->m_tail,chunk_get(_chunk,index));
    }
    _chunk->m_tail = chunk_get(_chunk,index);
    }
    ++_chunk->m_freesize;
    }

    inline unsigned int chunk_GetFreeSize(struct chunk *_chunk)
    {
    return _chunk->m_freesize;
    }

    inline char *chunk_GetBlocksAddr(struct chunk *_chunk)
    {
    return (char*)_chunk->m_blocks;
    }

    inline char *chunk_GetLastAddr(struct chunk *_chunk)
    {
    return (char*)block_GetLastAddr(chunk_get(_chunk,_chunk->block_count-1));
    }

    inline void chunk_SetNext(struct chunk *_chunk, struct chunk * next)
    {
    _chunk->m_next = next;
    }

    inline struct chunk *chunk_GetNext(struct chunk *_chunk)
    {
    return _chunk->m_next;
    }

    #define DEFAULT_CHUNK_COUNT 128 //当chunk数量大于此值时将采用动态分配
    struct fix_obj_pool
    {
    struct chunk *m_lastDeAlloc;
    struct chunk *m_head;
    struct chunk *m_tail;
    struct chunk **ptr_chunk;
    unsigned int chunk_count;
    unsigned int obj_size;
    int default_size;
    struct chunk *chunks[DEFAULT_CHUNK_COUNT];
    };

    unsigned int alignsize(unsigned int obj_size)
    {
    if(obj_size % 4 > 0)
    obj_size = (obj_size / 4) * 4 + 4;
    return obj_size;
    }


    struct fix_obj_pool *create_pool(unsigned int obj_size,int default_size,int align4)
    {
    //将default_size规整为128的倍数
    if(default_size <= 0)
    default_size = BLOCK_OBJ_SIZE;
    else
    {
    if(default_size % BLOCK_OBJ_SIZE > 0)
    default_size = (default_size / BLOCK_OBJ_SIZE) * BLOCK_OBJ_SIZE + BLOCK_OBJ_SIZE;
    }

    struct fix_obj_pool *pool = malloc(sizeof(*pool));
    if(pool)
    {
    if(align4)
    obj_size = alignsize(obj_size);
    struct chunk *_chunk = chunk_create(default_size/BLOCK_OBJ_SIZE,obj_size);
    pool->m_lastDeAlloc = 0;
    pool->m_head = pool->m_tail = _chunk;
    pool->chunk_count = 1;
    pool->ptr_chunk = pool->chunks;
    pool->ptr_chunk[0] = _chunk;
    pool->obj_size = obj_size;
    pool->default_size = default_size;
    }
    return pool;

    }

    void destroy_pool(struct fix_obj_pool **pool)
    {
    unsigned int i = 0;
    for( ; i < (*pool)->chunk_count; ++i)
    chunk_destroy(&((*pool)->ptr_chunk[i]));
    if((*pool)->ptr_chunk != (*pool)->chunks)
    free((*pool)->ptr_chunk);
    free(*pool);
    }


    void* pool_alloc(struct fix_obj_pool *pool)
    {

    void *ret = chunk_alloc(pool->m_head);
    if(chunk_GetFreeSize(pool->m_head) == 0)
    {
    pool->m_head = chunk_GetNext(pool->m_head);
    if(!pool->m_head)
    {
    //没有空间了,扩展新的块
    struct chunk *_chunk = chunk_create(pool->default_size/BLOCK_OBJ_SIZE,pool->obj_size);
    if(!_chunk)
    return 0;
    pool->m_head = pool->m_tail = _chunk;
    pool->chunk_count++;
    if(pool->chunk_count > DEFAULT_CHUNK_COUNT)
    {
    struct chunk **tmp = malloc(sizeof(*tmp)*pool->chunk_count);
    int i = 0;
    for( ; i < pool->chunk_count - 1;++i)
    tmp[i] = pool->ptr_chunk[i];
    tmp[pool->chunk_count - 1] = _chunk;

    if(pool->ptr_chunk != pool->chunks)
    free(pool->ptr_chunk);
    pool->ptr_chunk = tmp;
    }

    //对所有的chunk按其地址顺序排序
    unsigned int size = pool->chunk_count;
    int i = size-2;
    for( ; i >= 0; --i)
    {
    if(pool->m_head < pool->ptr_chunk[i])
    {
    struct chunk *tmp = pool->ptr_chunk[i];
    pool->ptr_chunk[i] = pool->m_head;
    pool->ptr_chunk[i+1] = tmp;
    }
    else
    {
    pool->ptr_chunk[i+1] = pool->m_head;
    break;
    }
    }
    }
    }
    return ret;
    }

    struct chunk *BinSearch(struct fix_obj_pool *pool,void *obj)
    {
    int beg = 0;
    int end = (int)pool->chunk_count;
    int len = end - beg;
    while(len > 0)
    {
    int mid = beg + len/2;

    if(chunk_check(pool->ptr_chunk[mid],obj) == 1)
    return pool->ptr_chunk[mid];
    else if((char*)obj > chunk_GetBlocksAddr(pool->ptr_chunk[mid]))
    beg = mid + 1;
    else
    end = mid - 1;
    len = end - beg;
    }
    if(chunk_check(pool->ptr_chunk[beg],obj) == 1)
    return pool->ptr_chunk[beg];
    return 0;
    }

    void pool_dealloc(struct fix_obj_pool *pool,void* obj)
    {
    struct chunk *_chunk = pool->m_lastDeAlloc;
    if(!_chunk || chunk_check(_chunk,obj) == 0)
    _chunk = BinSearch(pool,obj);
    if(_chunk)
    {
    chunk_dealloc(_chunk,obj);
    if(chunk_GetFreeSize(_chunk) == 1)
    {
    if(pool->m_head)
    {
    chunk_SetNext(pool->m_tail,_chunk);
    pool->m_tail = _chunk;
    }
    else
    pool->m_head = pool->m_tail = _chunk;
    }
    pool->m_lastDeAlloc = _chunk;
    }
    }

    unsigned int get_free_size(struct fix_obj_pool *pool)
    {
    unsigned int totalsize = 0;
    int i = 0;
    for( ; i < pool->chunk_count; ++i)
    {
    totalsize += chunk_GetFreeSize(pool->ptr_chunk[i]);
    }
    return totalsize;
    }



  • 相关阅读:
    [zjoi]青蛙的约会_扩展欧几里德
    [coci2012]覆盖字符串 AC自动机
    出题日志
    [zjoi2003]密码机
    矩阵乘法
    洛谷 P1064 金明的预算方案
    洛谷 P1656 炸铁路
    洛谷 P1049 装箱问题
    最长上升子序列(LIS)与最长公共子序列(LCS)
    求最大公约数与最小公倍数
  • 原文地址:https://www.cnblogs.com/sniperHW/p/2429612.html
Copyright © 2011-2022 走看看