driver/sliding_expiration_cache.cc (95 lines of code) (raw):

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0 // (GPLv2), as published by the Free Software Foundation, with the // following additional permissions: // // This program is distributed with certain software that is licensed // under separate terms, as designated in a particular file or component // or in the license documentation. Without limiting your rights under // the GPLv2, the authors of this program hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have included with the program. // // Without limiting the foregoing grant of rights under the GPLv2 and // additional permission as to separately licensed software, this // program is also subject to the Universal FOSS Exception, version 1.0, // a copy of which can be found along with its FAQ at // http://oss.oracle.com/licenses/universal-foss-exception. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License, version 2.0, for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // http://www.gnu.org/licenses/gpl-2.0.html. #include "sliding_expiration_cache.h" #include <string> #include <utility> #include <vector> #include "custom_endpoint_monitor.h" template <class K, class V> void SLIDING_EXPIRATION_CACHE<K, V>::remove_and_dispose(K key) { if (this->cache.count(key)) { std::shared_ptr<CACHE_ITEM> cache_item = this->cache[key]; if (item_disposal_func != nullptr) { item_disposal_func->dispose(cache_item->item); } this->cache.erase(key); } } template <class K, class V> void SLIDING_EXPIRATION_CACHE<K, V>::clean_up() { if (this->clean_up_time_nanos.load() > std::chrono::steady_clock::now()) { return; } this->clean_up_time_nanos = std::chrono::steady_clock::now() + std::chrono::nanoseconds(this->clean_up_interval_nanos); std::vector<K> keys; keys.reserve(this->cache.size()); for (auto& [key, cache_item] : this->cache) { keys.push_back(key); } for (const auto& key : keys) { this->remove_if_expired(key); } } template <class K, class V> V SLIDING_EXPIRATION_CACHE<K, V>::compute_if_absent(K key, std::function<V(K)> mapping_function, long long item_expiration_nanos) { this->clean_up(); V item = mapping_function(key); auto cache_item = std::make_shared<CACHE_ITEM>(item, std::chrono::steady_clock::now() + std::chrono::nanoseconds(item_expiration_nanos)); this->cache.emplace(key, cache_item); return cache_item->with_extend_expiration(item_expiration_nanos)->item; } template <class K, class V> V SLIDING_EXPIRATION_CACHE<K, V>::put(K key, V value, long long item_expiration_nanos) { this->clean_up(); std::shared_ptr<CACHE_ITEM> cache_item = std::make_shared<CACHE_ITEM>( std::move(value), std::chrono::steady_clock::now() + std::chrono::nanoseconds(item_expiration_nanos)); this->cache[key] = cache_item; return cache_item->with_extend_expiration(item_expiration_nanos)->item; } template <class K, class V> V SLIDING_EXPIRATION_CACHE<K, V>::get(K key, long long item_expiration_nanos, V default_value) { this->clean_up(); if (this->cache.count(key)) { std::shared_ptr<CACHE_ITEM> cache_item = this->cache[key]; return cache_item->with_extend_expiration(item_expiration_nanos)->item; } return default_value; } template <class K, class V> void SLIDING_EXPIRATION_CACHE<K, V>::remove(K key) { this->remove_and_dispose(std::move(key)); clean_up(); } template <class K, class V> void SLIDING_EXPIRATION_CACHE<K, V>::clear() { std::vector<K> keys; keys.reserve(this->cache.size()); for (auto& [key, cache_item] : this->cache) { keys.push_back(key); } for (const auto& key : keys) { this->remove_and_dispose(key); } this->cache.clear(); } template <class K, class V> std::unordered_map<K, V> SLIDING_EXPIRATION_CACHE<K, V>::get_entries() { std::unordered_map<K, V> entries; for (auto& [key, cache_item] : this->cache) { entries[key] = cache_item->item; } return entries; } template <class K, class V> int SLIDING_EXPIRATION_CACHE<K, V>::size() { return this->cache.size(); } template <class K, class V> void SLIDING_EXPIRATION_CACHE<K, V>::set_clean_up_interval_nanos(long long clean_up_interval_nanos) { this->clean_up_interval_nanos = clean_up_interval_nanos; this->clean_up_time_nanos.store(std::chrono::steady_clock::now() + std::chrono::nanoseconds(clean_up_interval_nanos)); } template class SLIDING_EXPIRATION_CACHE<std::string, std::string>; template class SLIDING_EXPIRATION_CACHE<std::string, std::shared_ptr<CUSTOM_ENDPOINT_MONITOR>>; template class SHOULD_DISPOSE_FUNC<std::shared_ptr<CUSTOM_ENDPOINT_MONITOR>>; template class ITEM_DISPOSAL_FUNC<std::shared_ptr<CUSTOM_ENDPOINT_MONITOR>>;