transmission/libtransmission/lru-cache.h
Charles Kerr d11cddc39a
fix: sonarcloud warnings (#6615)
* fix: cpp:S3358 conditional-operators-should-not-be-nested warning in gtk client

* fix: cpp:S1659 define-each-identifier-in-a-dedicated-statement warning in peer-mgr-wishlist

* Revert "fix; cpp:S3642 replace-enum-with-enum-class warning in gtk client"

* fix: cpp:S3576 remove-virtual-specifier-or-replace-it-by-override warning in rpc-server::Settings

* fix: cpp:S3576 remove-virtual-specifier-or-replace-it-by-override warning in tr_session_alt_speeds::Settings

* fix: remove unnecessary Settings subclass declarations

* fix: cpp:S1117 shadow warning in qt client

* fix: cpp:S6004 use init-statement to limit scope of local

* fix: cpp:S5997 replace-std-lock-guard-with-std-sccoped-lock in favicon-cache.h

* fix: cpp:S1659 define-each-identifier-in-a-dedicated-statement warning in announcer

* fix: cpp:S5817 function-should-be-declared-const warning in cache.h

* fix: cpp:S1186 explain-why-method-is-empty warning in favicon-cache

* fix: cpp:S5408 constexpr-variables-should-not-be-declared-inline warning in favicon-cache

* fix: cpp:S3624 explicitly delete copy assignment, ctor of InFlightData

* fix: cpp:S5997 use std-scoped-lock-instead-of-std-lock-guard

* fix: cpp:S5997 use std-scoped-lock-instead-of-std-lock-guard

* fix: cpp:S5817 function-should-be-declared-const warning in favicon-cache.h

* fix: cpp:S5817 function-should-be-declared-const warning in lru-cache

* fix: cpp:S1709 add-the-explicit-keyword-to-this-constructor
2024-02-17 22:43:24 -06:00

127 lines
2.8 KiB
C++

// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#pragma once
#include <array>
#include <cstddef> // size_t
#include <cstdint>
#include <functional>
#include <utility>
// A fixed-size cache that erases least-recently-used items to make room for new ones.
template<typename Key, typename Val, std::size_t N>
class tr_lru_cache
{
public:
[[nodiscard]] constexpr Val* get(Key const& key) noexcept
{
if (auto const found = find(key); found != nullptr)
{
found->sequence_ = next_sequence_++;
return &found->val_;
}
return nullptr;
}
[[nodiscard]] constexpr bool contains(Key const& key) const noexcept
{
return find(key) != nullptr;
}
Val& add(Key&& key)
{
auto& entry = get_free_slot();
entry.key_ = std::move(key);
entry.sequence_ = next_sequence_++;
key = {};
return entry.val_;
}
void erase(Key const& key)
{
if (auto* const found = find(key); found != nullptr)
{
this->erase(*found);
}
}
void erase_if(std::function<bool(Key const&, Val const&)> test)
{
for (auto& entry : entries_)
{
if (entry.sequence_ != InvalidSeq && test(entry.key_, entry.val_))
{
erase(entry);
}
}
}
void clear()
{
for (auto& entry : entries_)
{
erase(entry);
}
}
private:
struct Entry
{
Key key_ = {};
Val val_ = {};
uint64_t sequence_ = InvalidSeq;
};
void erase(Entry& entry) const
{
entry.key_ = {};
entry.val_ = {};
entry.sequence_ = InvalidSeq;
}
[[nodiscard]] constexpr Entry* find(Key const& key) noexcept
{
for (auto& entry : entries_)
{
if (entry.sequence_ != InvalidSeq && entry.key_ == key)
{
return &entry;
}
}
return nullptr;
}
[[nodiscard]] constexpr Entry const* find(Key const& key) const noexcept
{
for (auto const& entry : entries_)
{
if (entry.sequence_ != InvalidSeq && entry.key_ == key)
{
return &entry;
}
}
return nullptr;
}
Entry& get_free_slot()
{
auto const iter = std::min_element(
std::begin(entries_),
std::end(entries_),
[](auto const& a, auto const& b) { return a.sequence_ < b.sequence_; });
erase(*iter);
return *iter;
}
std::array<Entry, N> entries_;
uint64_t next_sequence_ = 1U;
static uint64_t constexpr InvalidSeq = 0U;
};