一个图片缓冲区的设计

转载请注明出处: http://www.pengliu.org/proj/cache_buf.html

简介

在 GUI 系统、游戏开发等场景中经常需要提供对图片的缓存管理,本人结合实 际项目经验提供了一种基于哈希表和双向链表的图片缓冲区设计方法。

数据结构

使用哈西表组织和管理所有的数据,首先用哈希函数计算字符串在哪个链表,然 后根据 md5 值顺序比较链表元素,查找对应的字符。

哈希队列数据结构示意图如下所示:

哈希队列示意图
哈希队列示意图

哈希链表结点如下图所示:

链表结点结构图
链表结点结构图

数据结构代码如下所示:

typedef struct _RESCACHENODE {

    unsigned char key[MD5_LENTH];
    IMAGE* *bmp;
    int ref_count;
    int is_preload;

    _RESCACHNODE* pre;
    _RESCACHNODE* next;

} RESCACHENODE;


#define NR_HASH_ENTRIES     20

typedef struct  _RESCACHE {

    RECACHENODE* res_hash_table [NR_HASH_ENTRIES];

} RESCACHE;

RESCACHE res_cache = {0};

哈希函数

基于 md5 值的哈希函数:


static int hashfn (unsigned char* key)
{
    /*if NR_HASH_ENTRIES<=255*/
    entry = md5_str[0] % NR_HASH_ENTRIES
}

基于字符求和的哈希函数:


static int hash_string (const char* key)
{
    int hval;
    const char* ptr = (const char*) key;
    char c;
    int i;

    hval = 0;
    for (i = 1; (c = *ptr++); i++)
        hval += c * i;

    return (hval % NR_HASH_ENTRIES);
}

数据管理接口


/*
 * Read images files top dir.
 **/
static BOOL set_res_top_dir (void);

/* Init cache: set top dir and initialize lock **/
void init_cache (void);

/*
 * Load the file to IMAGE object , add a new node to the cache and
 * set is_preload to FALSE.
 * If the node already exists, then ref_count ++; Otherwise, load
 * the Bitmap.
 *
 * hdc: dc
 * file: key value
 * Return:  If succeed, return TRUE; Otherwise return FALSE.
 */
BOOL RegisterResFromFile (HDC hdc, const char *file);


/*
 * Load the memory data to IMAGE object, create a new node to the cache
 * and set is_preload to FALSE.
 * If the node already exists, then ref_count ++; Otherwise, load the
 * image object.
 *
 * hdc: dc
 * file: key value
 * Return:  If succeed, return TRUE; Otherwise return FALSE.
 **/
BOOL
RegisterResFromMem (HDC hdc, const char* key, const unsigned char* data,
        size_t data_size);


/*
 * Load the image object to the cache with the key value and set is_preload
 * to TRUE.
 * If the node already exists, then ref_count ++; Otherwise, add a new node to
 * the cache.
 *
 * file: key value
 * image: IMAGE object.
 **/
BOOL RegisterResFromBitmap (const char* key, const IMAGE* bmp);



/*
 * Find  an IMAGE object in cache with the key value "file".
 *
 * file: key value
 * If found, then return the pointer of the image; Otherwise, return NULL;
 */
IMAGE* RetrieveRes (const char *file);

/*
 * Unregister the IMAGE object.
 * If ref_count > 1, then refcount --; Otherwise, unload the IMAGE object
 * and detach the node from the cache.
 * If is_preload == TRUE, then do not unload IMAGE object.
 *
 * file: key value
 * image: image object.
 */
void GUIAPI UnregisterRes (const char *file);

foot bar