concurrent_lru_cache模板类

本文介绍了一种基于模板类的并发LRU缓存实现,该缓存能够限制存储未使用的对象数量,并允许多线程并发检索。文章还提供了一个简单的LRU缓存示例,采用哈希表加双向链表的方式实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

汇总

最近最少使用缓存的并发操作的模板类

语法

template <typename key_type, typename value_type, typename value_functor_type = value_type (*)(key_type) >
 class concurrent_lru_cache;

头文件

#define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1
 #include "tbb/concurrent_lru_cache.h"

描述

concurrent_lru_cache container maps keys to values with the ability to limit the number of stored unused objects. There is at most one element in the container for each key.

The container permits multiple threads to concurrently retrieve items from it.

The container tracks the lifetime of retrieved items by returning a proxy object instead of a real value.

The container stores all the items that are currently in use and a limited number of unused items. Extra items are removed in a least recently used manner.

When no item is found for a key, the container calls the user provided function object to get a needed value and inserts it. The functor object must be thread safe.

成员函数

namespace tbb {
 template <typename key_type,
 typename value_type,
 typename value_functor_type = value_type (*)(key_type) >
 class concurrent_lru_cache{
 private:
 class handle_object;
 public:
 typedef handle_object handle;
 public:
 concurrent_lru_cache(value_functor_type f,std::size_t number_of_lru_history_items);
 handle_object operator()(key_type k);
 private:
 struct handle_move_t;
 class handle_object {
 public:
 handle_object(handle_move_t m);
 operator handle_move_t();
 value_type& value();
 ~handle_object();
 friend handle_move_t move(handle_object& h);
 private:
 void operator=(handle_object&);
 handle_object(handle_object &);
 };
};
 }
The following table provides additional information on the members of this template class.
Member Description
concurrent_lru_cache(value_function_type f,std::size_tnumber_of_lru_history_items);

Constructs an empty cache with a number_of_lru_history_items maximum number of stored unused objects, and f function object returning new values.

handle_object operator[](key_type k)

Search the container for a pair with given key. If the pair is not found, the user provided function object is called to get the value and insert it into the container.

Returnshandle_object pointing to the matching value.

~ concurrent_lru_cache ()

Destroys all items in the container, and the container itself, so that it can no longer be used.

handle_object class More Info
handle_move_t class

This is an instrumental class to allow certain conversions that allow ownership transfer between instances of handle_object objects. As well it allowshandle_object objects to be passed to and returned from functions. The class has no members other than holding a reference to value object in LRU cache container and a pointer to the container itself.


handle_object class

汇总

提供了读和写访问concurrent_lru_cache值的

语法

template <typename key_type,
 typename value_type,
 typename value_functor_type = value_type (*)(key_type) >
 class concurrent_lru_cache::handle_object {

头文件

#include "tbb/concurrent_lru_cache.h"

描述

handle_object is a (smart handle) proxy object returned by the cache container allowing getting reference to the value.

Live object of this type prevents the container from erasing values while they are being used.

The handle_object does not have copy semantics; instead it only allows transfer of ownership i.e. it semantics is similar to one of std::auto_ptr or move semantics from C++11.

成员函数和独立的功能

namespace tbb {
 template <typename key_type,
 typename value_type,
 typename value_functor_type = value_type (*)(key_type) >
 class concurrent_lru_cache::handle_object {
 public:
 handle_object(handle_move_t m);
 operator handle_move_t();
 value_type& value();
 ~handle_object();
 private:
 void operator=(handle_object&);
 handle_object(handle_object &);
 };
};
 handle_move_t move(handle_object& h);
 }
The following table provides additional information on the members of this template class.
Member Description
handle_object(handle_move_t m)

Constructs an handle_object object from a pointer or from another handle_object (through implicit conversion to handle_move_t object).

Since handle_object objects owns a reference to a value object of LRU cache, when a new handle_object is constructed from anotherhandle_object, the former owner releases the reference ownership (i.e. no longer refers to any value) .

operator handle_move_t()

This method should not be called directly, instead use free standing move function.

Effects: Transfer reference ownership from handle_object objects to temporary handle_move_t object.

Returnshandle_move_t object pointing to the same value object of LRU cache

value_type& value()

Return a reference to value object of LRU cache container.

Returns: Reference to value_type object inside the LRU cache container.

~handle_object()

Release a reference to value object of LRU cache container. It it was the last reference to the value object the container is allowed to evict the value.





// A simple LRU cache written in C++
// Hash map + doubly linked list
#include <iostream>
#include <vector>
#include <ext/hash_map>
using namespace std;
using namespace __gnu_cxx;


template <class K, class T>
struct Node{
    K key;
    T data;
    Node *prev, *next;
};


template <class K, class T>
class LRUCache{
public:
    LRUCache(size_t size){
        entries_ = new Node<K,T>[size];
        for(int i=0; i<size; ++i)// 存储可用结点的地址
            free_entries_.push_back(entries_+i);
        head_ = new Node<K,T>;
        tail_ = new Node<K,T>;
        head_->prev = NULL;
        head_->next = tail_;
        tail_->prev = head_;
        tail_->next = NULL;
    }
    ~LRUCache(){
        delete head_;
        delete tail_;
        delete[] entries_;
    }
    void Put(K key, T data){
        Node<K,T> *node = hashmap_[key];
        if(node){ // node exists
            detach(node);
            node->data = data;
            attach(node);
        }
        else{
            if(free_entries_.empty()){// 可用结点为空,即cache已满
                node = tail_->prev;
                detach(node);
                hashmap_.erase(node->key);
            }
            else{
                node = free_entries_.back();
                free_entries_.pop_back();
            }
            node->key = key;
            node->data = data;
            hashmap_[key] = node;
            attach(node);
        }
    }
    T Get(K key){
        Node<K,T> *node = hashmap_[key];
        if(node){
            detach(node);
            attach(node);
            return node->data;
        }
        else{// 如果cache中没有,返回T的默认值。与hashmap行为一致
            return T();
        }
    }
private:
    // 分离结点
    void detach(Node<K,T>* node){
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }
    // 将结点插入头部
    void attach(Node<K,T>* node){
        node->prev = head_;
        node->next = head_->next;
        head_->next = node;
        node->next->prev = node;
    }
private:
    hash_map<K, Node<K,T>* > hashmap_;
    vector<Node<K,T>* > free_entries_; // 存储可用结点的地址
    Node<K,T> *head_, *tail_;
    Node<K,T> *entries_; // 双向链表中的结点
};


int main(){
    hash_map<int, int> map;
    map[9]= 999;
    cout<<map[9]<<endl;
    cout<<map[10]<<endl;
    LRUCache<int, string> lru_cache(100);
    lru_cache.Put(1, "one");
    cout<<lru_cache.Get(1)<<endl;
    if(lru_cache.Get(2) == "")
        lru_cache.Put(2, "two");
    cout<<lru_cache.Get(2);
    return 0;
}
# 角色:系统测试工程师 ## 背景:擅长系统测试设计,擅长系统测试、自动化测试,安全测试等,是个综合的高级测试工程师 # 任务:根据用户输入的需求描述,完成测试设计 ##需求描述:‘’’在greenplum数据库中,要求如下:1、能够准确的进行select 类sql 的结果缓存;2、能够准确的对执行的sql 命中,并保存在对应的共享内存中;3、能够sql 语句缓存数量达到上限,能够进行更新替换掉原先缓存的sql 语句;4、对数据库进行一个并发的测试,高并发的条件下,仍然能够有效的进行以上1,2,3 的功能。‘’‘ ##测试脚本参考:’‘’ ## 测试脚本使用手册 供参考,脚本可根据具体环境细微调整, psql 语句参数要根据具体环境信息进行更改。 ## 拷贝本文件内所有脚本到数据库用户目录下,master节点 三个脚本能够执行,目录内能新建文件夹,编辑文件即可。 ## 编译安装 sql_cache 在 sql_cache 文件夹中,make clean && make install 会有生成共享库 sql_cache.so ,加入到master节点的pg共享库 ## 修改master节点的配置文件 postgresql.conf 添加 shared_preload_libraries='sql_cache' ***需要重启数据库集群才能生效*** sql查看是否成功配置 sql_cache show shared_preload_libraries ; ## 运行脚本, sh test.sh 会提示输入参数,参数说明。 testselectnum : 一个sql文件中sql 查询语句执行多少条, test_count_time : sql文件循环执行执行多少遍, test_concurrent_num : 并发数,测试并发所用,不建议设置并发数太大,测试宿主机本身资源也有限制,可按要求自行设置参数。 loglevel: 日志级别, 默认LOG, 调试可以使用DEBUG1 ## 测试输出 test_sql_cache_log 文件夹记录循环执行的输出 test_sql_cache_concurrent_log 文件夹记录并发执行的输出 ‘’‘ ##输出格式要求:按照需求描述输出测试设计,格式为markdown格式
最新发布
03-14
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值