汇总
最近最少使用缓存的并发操作的模板类。
语法
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"
描述
A 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 &); }; }; }
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. Returns: handle_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"
描述
A 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); }
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. Returns: handle_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. |
// 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;
}