雜湊鏈表實現的LRU緩衝演算法

來源:互聯網
上載者:User

在做三角網格檔案轉換的時候需要對從檔案中讀取的頂點座標進行緩衝,於是索性做了一個雜湊緩衝以提高訪問效率,同時以LRU原則在緩衝滿的情況下清楚緩衝中的單元。在hash表中我用了最簡單的取摸的方法,由於原頂點有一個索引而且這種索引連續,所以取摸的方法已經可以達到平均散列。在處理碰撞的時候我使用了鏈表,而所有在緩衝中的單元都按放入緩衝的時間串成一個鏈表,這樣在清除單元的時候選擇隊尾的元素進行清除即可。

/*    manipulations for the vertex binary file    there is a least recent used hash cache    for reading vertices    the hash bucket with lru list is like this    _____________        _____          _____    |bucket_head| ---->  |   | -> .. -> |   | -> Null    _____________        _____          _____    |bucket_head| ---->  |   | -> .. -> |   | -> Null    _____________            |bucket_head| ---->  Null        ...    _____________        _____          _____    |bucket_head| ---->  |   | -> .. -> |   | -> Null    while all the nodes in the buckets are linked    based on the time they are accessed, thus the    newly accessed node are inserted into the head    of the lru list, if it has already existed in    the list, it will be deleted from the list first    author: waytofall*/#include <fstream>#include <iostream>using namespace std;class VertexBinary{    typedef struct __Vertex    {        float x, y, z;    } __Vertex;    typedef struct __CacheUnit    {        struct __CacheUnit *bucket_prev; // bucket pointer        struct __CacheUnit *bucket_next;        struct __CacheUnit *use_prev; // lru pointer         struct __CacheUnit *use_next;        __Vertex vert;        unsigned int index;    } __CacheUnit;public:    VertexBinary();    ~VertexBinary();    /* write */    int openForWrite(const char* filename);    int closeWriteFile();    int writeVertexFloat(float x, float y, float z);    /* read */    int initCache(unsigned int size);    int openForRead(const char* filename);    int indexedRead(unsigned int index);    int closeReadFile();    float getXFloat();    float getYFloat();    float getZFloat();    void writeCacheDebug();private:    void insertBucketList(__CacheUnit **head, __CacheUnit *new_unit);    void deleteBucketList(__CacheUnit **head, __CacheUnit *unit);    void insertLruList(__CacheUnit *new_unit);    void deleteLruList(__CacheUnit *unit);    int indexedReadFromFile(unsigned int index, float &x, float &y, float &z);private:    ifstream fin;    ofstream fout;    unsigned int cache_size;    unsigned int cache_count;    __CacheUnit **cache_bucket;    __CacheUnit *lru_head;    __CacheUnit *lru_tail;    __CacheUnit *current_unit;public:    unsigned int read_count;    unsigned int hit_count;};

/*    manipulations for the vertex binary file    author: waytofall*/#include "vert_bin.h"#include <fstream>#include <iostream>// if dump the cache to the file//#define _WRITE_CACHE_DEBUGVertexBinary::VertexBinary(){    cache_bucket = NULL;    cache_size = 0;    cache_count = 0;}VertexBinary::~VertexBinary(){    if (cache_bucket)    {        delete[] cache_bucket;    }}int VertexBinary::openForWrite(const char *filename){    fout.open(filename, ios::out | ios::binary);    if(fout.good())        return 1;    else        return 0;}int VertexBinary::writeVertexFloat(float x, float y, float z){    if (!fout.good())    {        return 0;    }    fout.write((char*)&x, sizeof(float));    fout.write((char*)&y, sizeof(float));    fout.write((char*)&z, sizeof(float));    return 1;}int VertexBinary::openForRead(const char* filename){    fin.open(filename, ios::binary | ios::in);    if (fin.good())        return 1;    else        return 0;}int VertexBinary::indexedRead(unsigned int index){    if (cache_size <= 0)    {        cerr << "#error : no cache while indexed reading" << endl;        return 0;    }        read_count ++;    int hash_index = index % cache_size;    __CacheUnit *hit_unit = NULL;    // check if the cache hit    if(cache_bucket[hash_index])    {        __CacheUnit *bucket_head;        for(bucket_head = cache_bucket[hash_index]; bucket_head; bucket_head = bucket_head->bucket_next)        {            if (bucket_head->index == index)            {                hit_unit = bucket_head;                break;            }        }    }    // the the cache has the queried unit    if (hit_unit)    {        deleteLruList(hit_unit);        insertLruList(hit_unit);        current_unit = hit_unit;        hit_count ++;        return 1;    }    // the cache doesn't store the queried unit    // check if needed to delete the least recent used unit    if (cache_count == cache_size)    {        // delete the tail unit from the two lists        hit_unit = lru_tail;        deleteBucketList(&cache_bucket[hit_unit->index % cache_size], hit_unit);        deleteLruList(hit_unit);    }    else    {        hit_unit =  new __CacheUnit();        cache_count ++;    }    hit_unit->index = index;    indexedReadFromFile(index, hit_unit->vert.x, hit_unit->vert.y, hit_unit->vert.z);    insertBucketList(&cache_bucket[hash_index], hit_unit);    insertLruList(hit_unit);    current_unit = hit_unit;    #ifdef _WRITE_CACHE_DEBUG    writeCacheDebug();    #endif    return 1;}int VertexBinary::initCache(unsigned int size){    if(size <= 0)        return 0;    cache_size = size;    cache_bucket = new __CacheUnit*[cache_size];    for(unsigned int i = 0; i < cache_size; i ++)    {        cache_bucket[i] = NULL;    }    cache_count = 0;    lru_head = NULL;    lru_tail = NULL;    read_count = 0;     hit_count = 0;    return 1;}// insert from headvoid VertexBinary::insertBucketList(__CacheUnit **head, __CacheUnit *new_unit){    new_unit->bucket_prev = NULL;    new_unit->bucket_next = *head;    if (*head)    {        (*head)->bucket_prev = new_unit;    }    (*head) = new_unit;}// delete from any placevoid VertexBinary::deleteBucketList(__CacheUnit **head, __CacheUnit *unit){    if(*head == NULL)        return;    if(*head == unit)    {        *head = unit->bucket_next;    }    if (unit->bucket_prev)    {        unit->bucket_prev->bucket_next = unit->bucket_next;    }    if (unit->bucket_next)    {        unit->bucket_next->bucket_prev = unit->bucket_prev;    }}void VertexBinary::insertLruList(__CacheUnit *new_unit){    new_unit->use_prev = NULL;    new_unit->use_next = lru_head;    if (lru_head)    {        lru_head->use_prev = new_unit;    }    if (lru_head == NULL)    {        lru_tail = new_unit;    }    lru_head = new_unit;}// delete the lru list from the tailvoid VertexBinary::deleteLruList(__CacheUnit *unit){    if (lru_head == NULL)        return;    if (unit->use_next)    {        unit->use_next->use_prev = unit->use_prev;    }    if (unit->use_prev)    {        unit->use_prev->use_next = unit->use_next;    }        if (lru_head == unit)    {        lru_head = unit->use_next;    }    if (lru_tail == unit)    {        lru_tail = unit->use_prev;    }}int VertexBinary::indexedReadFromFile(unsigned int index, float &x, float &y, float &z){    if (!fin.good())    {        return 0;    }    fin.seekg(index * 3 * sizeof(float));    fin.read((char*)&x, sizeof(float));    fin.read((char*)&y, sizeof(float));    fin.read((char*)&z, sizeof(float));    return 1;}int VertexBinary::closeWriteFile(){    fout.close();    return 1;}int VertexBinary::closeReadFile(){    fin.close();    return 1;}float VertexBinary::getXFloat(){    return current_unit->vert.x;}float VertexBinary::getYFloat(){    return current_unit->vert.y;}float VertexBinary::getZFloat(){    return current_unit->vert.z;}void VertexBinary::writeCacheDebug(){    int i, c1, c2;    using namespace std;    ofstream fout ("cache_dump.txt", ios::out | ios::app);    __CacheUnit *pUnit;    for(i = 0, c1 = 0; i < cache_size; i ++)    {        if (cache_bucket[i] == NULL)            continue;        fout << "bucket #" << i << ": ";        for(pUnit = cache_bucket[i], c2 = 0; pUnit; pUnit = pUnit->bucket_next, c2 ++)        {            fout << pUnit->index << " ";        }        fout << "count: " << c2 << " " << endl;        c1 += c2;    }    fout << "total count: " << c1 << endl << "lru list: ";    for(c1 = 0, pUnit = lru_head; pUnit; pUnit = pUnit->use_next, c1 ++)    {        fout << pUnit->index << " ";    }    fout << endl << "lru count: " << c1 << endl << endl;    fout.close();}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.