// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2004-2006 Sage Weil * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * */ #ifndef CEPH_SIMPLECACHE_H #define CEPH_SIMPLECACHE_H #include "common/Mutex.h" #include "include/unordered_map.h" template , class H = std::hash > class SimpleLRU { Mutex lock; size_t max_size; ceph::unordered_map >::iterator, H> contents; list > lru; map pinned; void trim_cache() { while (lru.size() > max_size) { contents.erase(lru.back().first); lru.pop_back(); } } void _add(K key, V&& value) { lru.emplace_front(key, std::move(value)); // can't move key because we access it below contents[key] = lru.begin(); trim_cache(); } public: SimpleLRU(size_t max_size) : lock("SimpleLRU::lock"), max_size(max_size) { contents.rehash(max_size); } void pin(K key, V val) { Mutex::Locker l(lock); pinned.emplace(std::move(key), std::move(val)); } void clear_pinned(K e) { Mutex::Locker l(lock); for (typename map::iterator i = pinned.begin(); i != pinned.end() && i->first <= e; pinned.erase(i++)) { typename ceph::unordered_map >::iterator, H>::iterator iter = contents.find(i->first); if (iter == contents.end()) _add(i->first, std::move(i->second)); else lru.splice(lru.begin(), lru, iter->second); } } void clear(K key) { Mutex::Locker l(lock); typename ceph::unordered_map >::iterator, H>::iterator i = contents.find(key); if (i == contents.end()) return; lru.erase(i->second); contents.erase(i); } void set_size(size_t new_size) { Mutex::Locker l(lock); max_size = new_size; trim_cache(); } bool lookup(K key, V *out) { Mutex::Locker l(lock); typename ceph::unordered_map >::iterator, H>::iterator i = contents.find(key); if (i != contents.end()) { *out = i->second->second; lru.splice(lru.begin(), lru, i->second); return true; } typename map::iterator i_pinned = pinned.find(key); if (i_pinned != pinned.end()) { *out = i_pinned->second; return true; } return false; } void add(K key, V value) { Mutex::Locker l(lock); _add(std::move(key), std::move(value)); } }; #endif