userver: /data/code/userver/libraries/multi-index-lru/include/userver/multi-index-lru/container.hpp Source File
Loading...
Searching...
No Matches
container.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/multi-index-lru/container.hpp
4/// @brief @copybrief multi_index_lru::Container
5
6#include <boost/multi_index/identity.hpp>
7#include <boost/multi_index/ordered_index.hpp>
8#include <boost/multi_index/sequenced_index.hpp>
9#include <boost/multi_index_container.hpp>
10
11#include <boost/mpl/joint_view.hpp>
12#include <boost/mpl/list.hpp>
13
14#include <cstddef>
15#include <utility>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace multi_index_lru {
20
21/// @ingroup userver_containers
22///
23/// @brief MultiIndex LRU container
24template <typename Value, typename IndexSpecifierList, typename Allocator = std::allocator<Value> >
25class Container {
26public:
27 explicit Container(size_t max_size)
28 : max_size_(max_size)
29 {}
30
31 template <typename... Args>
32 bool emplace(Args&&... args) {
33 auto& seq_index = container_.template get<0>();
34 auto result = seq_index.emplace_front(std::forward<Args>(args)...);
35
36 if (!result.second) {
37 seq_index.relocate(seq_index.begin(), result.first);
38 } else if (seq_index.size() > max_size_) {
39 seq_index.pop_back();
40 }
41 return result.second;
42 }
43
44 bool insert(const Value& value) { return emplace(value); }
45
46 bool insert(Value&& value) { return emplace(std::move(value)); }
47
48 template <typename Tag, typename Key>
49 auto find(const Key& key) {
50 auto& primary_index = container_.template get<Tag>();
51 auto it = primary_index.find(key);
52
53 if (it != primary_index.end()) {
54 auto& seq_index = container_.template get<0>();
55 auto seq_it = container_.template project<0>(it);
56 seq_index.relocate(seq_index.begin(), seq_it);
57 }
58
59 return it;
60 }
61
62 template <typename Tag, typename Key>
63 bool contains(const Key& key) {
64 return this->template find<Tag, Key>(key) != container_.template get<Tag>().end();
65 }
66
67 template <typename Tag, typename Key>
68 bool erase(const Key& key) {
69 return container_.template get<Tag>().erase(key) > 0;
70 }
71
72 size_t size() const { return container_.size(); }
73 bool empty() const { return container_.empty(); }
74 size_t capacity() const { return max_size_; }
75
76 void set_capacity(size_t new_capacity) {
77 max_size_ = new_capacity;
78 auto& seq_index = container_.template get<0>();
79 while (container_.size() > max_size_) {
80 seq_index.pop_back();
81 }
82 }
83
84 void clear() { container_.clear(); }
85
86 template <typename Tag>
87 auto end() {
88 return container_.template get<Tag>().end();
89 }
90
91private:
92 using AdditionalIndices = boost::mpl::list<boost::multi_index::sequenced<> >;
93
94 using ExtendedIndexSpecifierList = boost::mpl::joint_view<AdditionalIndices, IndexSpecifierList>;
95
96 using BoostContainer = boost::multi_index::multi_index_container<Value, ExtendedIndexSpecifierList, Allocator>;
97
98 BoostContainer container_;
99 size_t max_size_;
100};
101} // namespace multi_index_lru
102
103USERVER_NAMESPACE_END