Skip to content

Commit 8d5ff07

Browse files
committed
Merge branch 'lru_miltiindex_prototype' into new_lru_multiindex_branch
2 parents 9b2b656 + d9e087b commit 8d5ff07

File tree

3 files changed

+54
-122
lines changed

3 files changed

+54
-122
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ name: Ubuntu
77
- master
88
- develop
99
- feature/**
10+
- lru_miltiindex_prototype
1011

1112
env:
1213
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64

libraries/multi-index-lru/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ target_include_directories(userver-multi-index-lru
1515
${Boost_INCLUDE_DIRS}
1616
PRIVATE
1717
"${CMAKE_CURRENT_SOURCE_DIR}/tests/"
18-
)
18+
)

libraries/multi-index-lru/include/userver/multi-index-lru/container.hpp

Lines changed: 52 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -3,173 +3,104 @@
33
/// @file userver/multi-index-lru/container.hpp
44
/// @brief @copybrief multi_index_lru::Container
55

6-
#include <boost/intrusive/link_mode.hpp>
7-
#include <boost/intrusive/list.hpp>
8-
#include <boost/intrusive/list_hook.hpp>
9-
#include <boost/multi_index/hashed_index.hpp>
10-
#include <boost/multi_index/mem_fun.hpp>
11-
#include <boost/multi_index/member.hpp>
6+
#include <boost/multi_index/sequenced_index.hpp>
7+
#include <boost/multi_index/identity.hpp>
8+
#include <boost/multi_index_container.hpp>
129
#include <boost/multi_index/ordered_index.hpp>
13-
#include <boost/multi_index/tag.hpp>
14-
#include <boost/multi_index_container.hpp>
1510

16-
#include <cstddef>
11+
#include <boost/mpl/list.hpp>
12+
#include <boost/mpl/joint_view.hpp>
13+
1714
#include <utility>
15+
#include <cstddef>
1816

1917
USERVER_NAMESPACE_BEGIN
2018

2119
namespace multi_index_lru {
2220

23-
namespace impl {
24-
25-
template <typename Value>
26-
struct ValueWithHook {
27-
Value value;
28-
mutable boost::intrusive::list_member_hook<> list_hook;
29-
30-
const ValueWithHook* GetPointerToSelf() const { return this; };
31-
32-
explicit ValueWithHook(const Value& val)
33-
: value(val)
34-
{}
35-
36-
explicit ValueWithHook(Value&& val)
37-
: value(std::move(val))
38-
{}
39-
40-
ValueWithHook() = delete;
41-
ValueWithHook(const ValueWithHook&) = delete;
42-
ValueWithHook(ValueWithHook&&) = delete;
43-
44-
ValueWithHook& operator=(const ValueWithHook&) = delete;
45-
ValueWithHook& operator=(ValueWithHook&&) = delete;
46-
47-
operator Value&() { return value; }
48-
operator const Value&() const { return value; }
49-
50-
Value* operator->() { return &value; }
51-
const Value* operator->() const { return &value; }
52-
53-
Value& get() { return value; }
54-
const Value& get() const { return value; }
55-
};
56-
57-
template <class List, class Node>
58-
void PushBackToList(List& lst, const Node& node) {
59-
lst.push_back(const_cast<Node&>(node)); // TODO:
60-
}
61-
62-
template <class List, class Node>
63-
void SpliceInList(List& lst, Node& node) {
64-
lst.splice(lst.end(), lst, lst.iterator_to(node));
65-
}
66-
67-
struct InternalPtrTag {};
68-
69-
} // namespace impl
7021

7122
/// @ingroup userver_containers
7223
///
7324
/// @brief MultiIndex LRU container
74-
template <typename Value, typename IndexSpecifierList, typename Allocator = std::allocator<impl::ValueWithHook<Value>>>
25+
template<
26+
typename Value,
27+
typename IndexSpecifierList,
28+
typename Allocator = std::allocator<Value>
29+
>
7530
class Container {
7631
public:
77-
explicit Container(size_t max_size)
78-
: max_size(max_size)
79-
{}
80-
81-
template <typename... Args>
32+
explicit Container(size_t max_size) : max_size(max_size) {}
33+
34+
template<typename... Args>
8235
bool emplace(Args&&... args) {
83-
if (container.size() >= max_size) {
84-
EvictLru();
85-
}
86-
87-
auto result = container.emplace(std::forward<Args>(args)...);
36+
auto result = container.emplace_front(std::forward<Args>(args)...);
8837

89-
auto& value = *result.first;
90-
if (result.second) {
91-
impl::PushBackToList(usage_list, value);
92-
} else {
93-
impl::SpliceInList(usage_list, value);
38+
if (result.second == false) {
39+
container.relocate(container.begin(),result.first);
40+
} else if (container.size() >= max_size) {
41+
container.pop_back();
9442
}
9543
return result.second;
9644
}
97-
45+
9846
bool insert(const Value& value) { return emplace(value); }
9947

10048
bool insert(Value&& value) { return emplace(std::move(value)); }
101-
102-
template <typename Tag, typename Key>
49+
50+
template<typename Tag, typename Key>
10351
auto find(const Key& key) {
10452
auto& primary_index = container.template get<Tag>();
10553
auto it = primary_index.find(key);
106-
54+
10755
if (it != primary_index.end()) {
108-
impl::SpliceInList(usage_list, *it);
56+
container.relocate(container.begin(),it);
10957
}
110-
58+
11159
return it;
11260
}
113-
114-
template <typename Tag>
115-
auto end() {
116-
return container.template get<Tag>().end();
117-
}
118-
119-
template <typename Tag, typename Key>
61+
62+
template<typename Tag, typename Key>
12063
bool contains(const Key& key) {
12164
return this->template find<Tag, Key>(key) != container.template get<Tag>().end();
12265
}
123-
124-
template <typename Tag, typename Key>
66+
67+
template<typename Tag, typename Key>
12568
bool erase(const Key& key) {
126-
auto& primary_index = container.template get<Tag>();
127-
auto it = primary_index.find(key);
128-
if (it != primary_index.end()) {
129-
usage_list.erase(usage_list.iterator_to(*it));
130-
}
13169
return container.template get<Tag>().erase(key) > 0;
13270
}
133-
134-
std::size_t size() const { return container.size(); }
71+
72+
size_t size() const { return container.size(); }
13573
bool empty() const { return container.empty(); }
136-
std::size_t capacity() const { return max_size; }
137-
74+
size_t capacity() const { return max_size; }
75+
13876
void set_capacity(size_t new_capacity) {
13977
max_size = new_capacity;
14078
while (container.size() > max_size) {
141-
EvictLru();
79+
container.pop_back();
14280
}
14381
}
144-
145-
void clear() { container.clear(); }
82+
83+
void clear() {
84+
container.clear();
85+
}
14686

14787
private:
148-
using CacheItem = impl::ValueWithHook<Value>;
149-
using List = boost::intrusive::list<
150-
CacheItem,
151-
boost::intrusive::member_hook<CacheItem, boost::intrusive::list_member_hook<>, &CacheItem::list_hook>>;
152-
153-
using ExtendedIndexSpecifierList = typename boost::mpl::push_back<
154-
IndexSpecifierList,
155-
boost::multi_index::hashed_unique<
156-
boost::multi_index::tag<impl::InternalPtrTag>,
157-
boost::multi_index::const_mem_fun<CacheItem, const CacheItem*, &CacheItem::GetPointerToSelf>>>::type;
88+
using AdditionalIndices = boost::mpl::list<
89+
boost::multi_index::sequenced<>
90+
>;
15891

159-
using BoostContainer = boost::multi_index::multi_index_container<CacheItem, ExtendedIndexSpecifierList, Allocator>;
92+
using ExtendedIndexSpecifierList =
93+
boost::mpl::joint_view<IndexSpecifierList, AdditionalIndices>;
16094

161-
void EvictLru() {
162-
if (!usage_list.empty()) {
163-
CacheItem* ptr_to_erase = &*usage_list.begin();
164-
usage_list.erase(usage_list.begin());
165-
container.template get<impl::InternalPtrTag>().erase(ptr_to_erase);
166-
}
167-
}
95+
using BoostContainer = boost::multi_index::multi_index_container<
96+
Value,
97+
ExtendedIndexSpecifierList,
98+
Allocator
99+
>;
168100

169101
BoostContainer container;
170-
std::size_t max_size;
171-
List usage_list;
102+
size_t max_size;
172103
};
173-
} // namespace multi_index_lru
104+
} // namespace multi_index_lru
174105

175-
USERVER_NAMESPACE_END
106+
USERVER_NAMESPACE_END

0 commit comments

Comments
 (0)