返回首页

简介
我想你知道什么是MRU高速缓存;否则,你不会阅读。这是一个非常简单的使用唯一的STL的的实现。
要实现高速缓存,从这个模板类派生一个子类。作为执行者,你就必须实施两种方法:HandleNonExistingKeyFetch - 处理高速缓存未命中。在此方法中,你背后的高速缓存访​​问的实时数据来源,并返回值。HandleItemRelease - (可选)从缓存中删除项目时。
Cache类是两种类型,键和值(如哈希映射)的模板。值类型是资源的类型,键的类型是资源的地址(这是你如何获取资源)的类型。源代码

#include <list>

#include <map>



/**

 * MRU Cache

 *

 * contains up to a fixed size of "Most Recently Used" items,

 * where items are assiciated with keys.

 * when asked to fetch a value that is not

 * in the cache, HandleNonExistingKeyFetch is called.

 * when an item is removed from the cache, HandleItemRelease is called.

 * implementor of this cache must provide those methods.

 *

 */

template <typename key_type, typename value_type>

class MruCache

{

public:

    

    const int maxLength;



    MruCache(int iMaxLength) : maxLength(iMaxLength) { }



    inline value_type FetchItem(key_type key) { return __fetch_item(key); }



    virtual  MruCache() { Clear(); }



    /**

     * clear the cache.

     * for every item contained, HandleItemRelease is called.

     */

    virtual void Clear() { __clear(); }





protected:



    virtual void HandleItemRelease(key_type key, value_type value) { };



    virtual value_type HandleNonExistingKeyFetch(key_type key) = 0;



private:



    typedef struct _Entry

    {

        key_type key;

        value_type value;

    } Entry;



    typedef std::list<Entry> EntryList;

    EntryList listOfEntries;



    /**

     * for fast search in the cache.

     * this map contains pointers to iterators in EntryList.

     */

    typedef std::map<key_type, void*> ItrPtrMap;

    ItrPtrMap mapOfListIteratorPtr;



    value_type __fetch_item(key_type key)

    {

        Entry entry;

        EntryList::iterator* ptrItr = 

           (EntryList::iterator*) mapOfListIteratorPtr[key];

        if (!ptrItr)

        {

            if ( (int)listOfEntries.size() >= maxLength)

            {

                Entry lruEntry = listOfEntries.back();

                HandleItemRelease(lruEntry.key, lruEntry.value);

                listOfEntries.pop_back();

                delete mapOfListIteratorPtr[lruEntry.key];

                mapOfListIteratorPtr.erase(lruEntry.key);

            }



            entry.value = HandleNonExistingKeyFetch(key);

            entry.key = key;

            listOfEntries.push_front(entry);



            EntryList::iterator* ptrItr = new EntryList::iterator();

            *ptrItr = listOfEntries.begin();

            mapOfListIteratorPtr[key] = ptrItr;

        }

        else

        {

            entry = *(*ptrItr);

            listOfEntries.erase(*ptrItr);

            listOfEntries.push_front(entry);

            *ptrItr = listOfEntries.begin();

        }

        return entry.value;

    }



    virtual void __clear()

    {

        for (ItrPtrMap::iterator i=mapOfListIteratorPtr.begin(); 

             i!=mapOfListIteratorPtr.end(); i++)

        {

            void* ptrItr = i->second;

            EntryList::iterator* pItr = (EntryList::iterator*) ptrItr;

            HandleItemRelease( (*pItr)->key, (*pItr)->value );

            delete ptrItr;

        }

        listOfEntries.clear();

        mapOfListIteratorPtr.clear();

    }

};

缓存本身是一个链表。最新的元素列表的开头。最近最少牵强元素结束。哈希映射用于访问quot元素;随机accessquot;时间。用法示例{C}

回答

评论会员:JacquesLeroy 时间:2011/12/14
迟早,缓存已满,你要申请的MRU / LRU策略...

下面的代码部分,可以显著改善...

如果((INT)listOfEntries.size()放大器; GT = MAXLENGTH)
{
入学lruEntry = listOfEntries.back()
HandleItemRelease(lruEntry.key,lruEntry.value)
listOfEntries.pop_back()
删除mapOfListIteratorPtr [lruEntry.key]

mapOfListIteratorPtr.erase(lruEntry.key); }

应注意,listOfEntries.back()返回一个引用,
有效期至listOfEntries.pop_back ()...{ BR}
和一个也应牢记两个

mapOfListIteratorPtr [lruEntry.key]和

mapOfListIteratorPtr.erase(lruEntry.key)

需要到地图搜索...

把这个产品总数驱使我们下面的
IF((INT)listOfEntries.size()放大器;放大器; GT = MAXLENGTH)
{
Entryamp; lruEntry = listOfEntries.back(); / /使用一个参考,避免调用入口构造器
! HandleItemRelease(lruEntry.key,lruEntry.value)

ItrPtrMap:迭代器POS = mapOfListIteratorPtr.find(lruEntry.key); / /搜索地图一次

删除(EntryList:迭代器*)POS - GT;第二; / /转换为避免内存泄漏

从地图mapOfListIteratorPtr.erase(POS); / /删除(键,值)对没有地图搜索

listOfEntries.pop_back(); / /删除listOfEntries lruEntry
}

总结:

- 我们避免调用条目构造器

_我们避免寻找地图两次相同的键


_ listOfEntries.pop_back();移动向下,以保持有效的参考lruEntry 只要有必要
评论会员:JacquesLeroy 时间:2011/12/14
内__clear()方法(白白是虚拟的,因为它是私有的),
有一个内存泄漏的原因!

{
&# 160;
无效* ptrItr = I - GT;第二; EntryList:迭代器* PITR =(EntryList:迭代器)ptrItr;
HandleItemRelease((* PITR)GT键,(* PITR)- GT;值);
  ;删除ptrItr;
}


(void *)的有:被删除!删除ptrItr;
正确的说法应该是:

删除PITR;

为了正确地调用迭代器析构函数和恢复记忆!

同样的问题也发生在高速缓存未命中的情况:

删除mapOfListIteratorPtr [lruEntry.key]

请记住,而地图是一个std::maplt; key_type,无效* GT;
我们店EntryList:在它的迭代*所以投是必需的:

删除(EntryList:迭代器*)mapOfListIteratorPtr [lruEntry.key]
评论会员:JacquesLeroy 时间:2011/12/14
是从类的析构函数中调用虚方法HandleItemRelease

这是一个在C的经典的原因。崩溃(或错误的行为)
(事实是,它是高度的C实现依赖)

解决方法是相当简单:MruCache类必须给予一些ItemHandler
在建设对象(提供ItemRelease和ItemFetch functionnality)
时间...
评论会员:tibzzz 时间:2011/12/14
您好,

我希望我的问题是不是太愚蠢了。

由于新的元素被压在了前面,要删除的元素是"poped回",似乎旧的元素都需要内存时,被删除的,而不是新的。

我想在MRU高速缓存,它的新元素,要删除旧的,因为有更多的机会要问。所以,我没有看到它作为一个MRU缓存...

我错了:
|