1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #ifndef CEPH_SIMPLECACHE_H
16 #define CEPH_SIMPLECACHE_H
20 #include <unordered_map>
23 #include "common/ceph_mutex.h"
25 template <class K, class V, class C = std::less<K>, class H = std::hash<K> >
27 ceph::mutex lock = ceph::make_mutex("SimpleLRU::lock");
30 size_t total_bytes = 0;
31 std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator, H> contents;
32 std::list<std::pair<K, V> > lru;
33 std::map<K, V, C> pinned;
36 while (contents.size() > max_size) {
37 contents.erase(lru.back().first);
42 void trim_cache_bytes() {
43 while(total_bytes > max_bytes) {
44 total_bytes -= lru.back().second.length();
45 contents.erase(lru.back().first);
50 void _add(K key, V&& value) {
51 lru.emplace_front(key, std::move(value)); // can't move key because we access it below
52 contents[key] = lru.begin();
56 void _add_bytes(K key, V&& value) {
57 lru.emplace_front(key, std::move(value)); // can't move key because we access it below
58 contents[key] = lru.begin();
63 SimpleLRU(size_t max_size) : max_size(max_size) {
64 contents.rehash(max_size);
67 void pin(K key, V val) {
68 std::lock_guard l(lock);
69 pinned.emplace(std::move(key), std::move(val));
72 void clear_pinned(K e) {
73 std::lock_guard l(lock);
74 for (auto i = pinned.begin();
75 i != pinned.end() && i->first <= e;
77 auto iter = contents.find(i->first);
78 if (iter == contents.end())
79 _add(i->first, std::move(i->second));
81 lru.splice(lru.begin(), lru, iter->second);
86 std::lock_guard l(lock);
87 auto i = contents.find(key);
88 if (i == contents.end())
90 total_bytes -= i->second->second.length();
95 void set_size(size_t new_size) {
96 std::lock_guard l(lock);
102 std::lock_guard l(lock);
103 return contents.size();
106 void set_bytes(size_t num_bytes) {
107 std::lock_guard l(lock);
108 max_bytes = num_bytes;
113 std::lock_guard l(lock);
117 bool lookup(K key, V *out) {
118 std::lock_guard l(lock);
119 auto i = contents.find(key);
120 if (i != contents.end()) {
121 *out = i->second->second;
122 lru.splice(lru.begin(), lru, i->second);
125 auto i_pinned = pinned.find(key);
126 if (i_pinned != pinned.end()) {
127 *out = i_pinned->second;
133 void add(K key, V value) {
134 std::lock_guard l(lock);
135 _add(std::move(key), std::move(value));
138 void add_bytes(K key, V value) {
139 std::lock_guard l(lock);
140 total_bytes += value.length();
141 _add_bytes(std::move(key), std::move(value));