6#include <userver/cache/impl/lru.hpp> 
    9 
   10
   11 
   12
   13
   14
   15
   16
   17
   18
   19 
   20
   21
   22
   23
   24
   25
   26 
   27
   29USERVER_NAMESPACE_BEGIN
 
   31namespace cache::
impl {
 
   33template <
typename T, 
typename U, 
typename Hash = std::hash<T>,
 
   34          typename Equal = std::equal_to<T>>
 
   37  using NodeType = std::unique_ptr<LruNode<T, U>>;
 
   39  explicit SlruBase(std::size_t probation_size, std::size_t protected_size,
 
   40                    const Hash& hash = Hash(), 
const Equal& equal = Equal());
 
   41  ~SlruBase() = 
default;
 
   43  SlruBase(SlruBase&& other) 
noexcept = 
default;
 
   45  SlruBase& operator=(SlruBase&& other) 
noexcept = 
default;
 
   47  SlruBase(
const SlruBase& slru) = 
delete;
 
   48  SlruBase& operator=(
const SlruBase& slru) = 
delete;
 
   50  bool Put(
const T& key, U value);
 
   52  template <
typename... Args>
 
   53  U* Emplace(
const T& key, Args&&... args);
 
   55  void Erase(
const T& key);
 
   59  const T* GetLeastUsedKey() 
const;
 
   61  U* GetLeastUsedValue();
 
   63  NodeType ExtractLeastUsedNode();
 
   65  void SetMaxSize(std::size_t new_probation_size,
 
   66                  std::size_t new_protected_size);
 
   68  void Clear() 
noexcept;
 
   70  template <
typename Function>
 
   71  void VisitAll(Function&& func) 
const;
 
   73  template <
typename Function>
 
   74  void VisitAll(Function&& func);
 
   76  std::size_t GetSize() 
const;
 
   78  std::size_t GetCapacity() 
const;
 
   80  U& InsertNode(NodeType&& node) 
noexcept;
 
   81  NodeType ExtractNode(
const T& key) 
noexcept;
 
   84  cache::
impl::LruBase<T, U, Hash, Equal> probation_part_;
 
   85  cache::
impl::LruBase<T, U, Hash, Equal> protected_part_;
 
   88template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
   89SlruBase<T, U, Hash, Equal>::SlruBase(std::size_t probation_size,
 
   90                                      std::size_t protected_size,
 
   91                                      const Hash& hash, 
const Equal& equal)
 
   92    : probation_part_(probation_size, hash, equal),
 
   93      protected_part_(protected_size, hash, equal) {}
 
   95template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
   96bool SlruBase<T, U, Hash, Equal>::Put(
const T& key, U value) {
 
   97  auto* 
const value_ptr = protected_part_.Get(key);
 
   99    *value_ptr = std::move(value);
 
  103  auto node_to_protected = probation_part_.ExtractNode(key);
 
  104  if (node_to_protected) {
 
  105    node_to_protected->SetValue(std::move(value));
 
  106    if (protected_part_.GetSize() == protected_part_.GetCapacity()) {
 
  107      auto node_to_probation = protected_part_.ExtractLeastUsedNode();
 
  108      probation_part_.InsertNode(std::move(node_to_probation));
 
  110    protected_part_.InsertNode(std::move(node_to_protected));
 
  114  return probation_part_.Put(key, std::move(value));
 
  117template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  118template <
typename... Args>
 
  119U* SlruBase<T, U, Hash, Equal>::Emplace(
const T& key, Args&&... args) {
 
  120  auto value_ptr = protected_part_.Get(key);
 
  125  auto node_to_protected = probation_part_.ExtractNode(key);
 
  126  if (node_to_protected) {
 
  127    return protected_part_.Emplace(key, std::forward<Args>(args)...);
 
  130  return probation_part_.Emplace(key, std::forward<Args>(args)...);
 
  133template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  134void SlruBase<T, U, Hash, Equal>::Erase(
const T& key) {
 
  135  probation_part_.Erase(key);
 
  136  protected_part_.Erase(key);
 
  139template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  140U* SlruBase<T, U, Hash, Equal>::Get(
const T& key) {
 
  141  auto value_ptr = protected_part_.Get(key);
 
  146  auto node_to_protected = probation_part_.ExtractNode(key);
 
  147  if (node_to_protected) {
 
  148    if (protected_part_.GetSize() == protected_part_.GetCapacity()) {
 
  149      auto node_to_probation = protected_part_.ExtractLeastUsedNode();
 
  150      probation_part_.InsertNode(std::move(node_to_probation));
 
  152    return &protected_part_.InsertNode(std::move(node_to_protected));
 
  157template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  158const T* SlruBase<T, U, Hash, Equal>::GetLeastUsedKey() 
const {
 
  159  return probation_part_.GetLeastUsedKey();
 
  162template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  163U* SlruBase<T, U, Hash, Equal>::GetLeastUsedValue() {
 
  164  return probation_part_.GetLeastUsedValue();
 
  167template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  168typename SlruBase<T, U, Hash, Equal>::NodeType
 
  169SlruBase<T, U, Hash, Equal>::ExtractLeastUsedNode() {
 
  170  return probation_part_.ExtractLeastUsedNode();
 
  173template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  174void SlruBase<T, U, Hash, Equal>::SetMaxSize(std::size_t new_probation_size,
 
  175                                             std::size_t new_protected_size) {
 
  176  probation_part_.SetMaxSize(new_probation_size);
 
  177  protected_part_.SetMaxSize(new_protected_size);
 
  180template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  181void SlruBase<T, U, Hash, Equal>::Clear() 
noexcept {
 
  182  probation_part_.Clear();
 
  183  protected_part_.Clear();
 
  186template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  187template <
typename Function>
 
  188void SlruBase<T, U, Hash, Equal>::VisitAll(Function&& func) 
const {
 
  189  probation_part_.VisitAll(std::forward<Function>(func));
 
  190  protected_part_.VisitAll(std::forward<Function>(func));
 
  193template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  194template <
typename Function>
 
  195void SlruBase<T, U, Hash, Equal>::VisitAll(Function&& func) {
 
  196  probation_part_.VisitAll(std::forward<Function>(func));
 
  197  protected_part_.VisitAll(std::forward<Function>(func));
 
  200template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  201std::size_t SlruBase<T, U, Hash, Equal>::GetSize() 
const {
 
  202  return probation_part_.GetSize() + protected_part_.GetSize();
 
  205template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  206std::size_t SlruBase<T, U, Hash, Equal>::GetCapacity() 
const {
 
  207  return probation_part_.GetCapacity() + protected_part_.GetCapacity();
 
  210template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  211U& SlruBase<T, U, Hash, Equal>::InsertNode(NodeType&& node) 
noexcept {
 
  212  return probation_part_.InsertNode(std::move(node));
 
  215template <
typename T, 
typename U, 
typename Hash, 
typename Equal>
 
  216typename SlruBase<T, U, Hash, Equal>::NodeType
 
  217SlruBase<T, U, Hash, Equal>::ExtractNode(
const T& key) 
noexcept {
 
  218  auto protected_node = protected_part_.ExtractNode(key);
 
  219  if (protected_node) {
 
  220    return protected_node;
 
  223  return probation_part_.ExtractNode(key);