Skip to content

Commit 740a6d5

Browse files
committed
fixes and docs
1 parent ed95cd9 commit 740a6d5

File tree

5 files changed

+58
-32
lines changed

5 files changed

+58
-32
lines changed

libraries/multi_index_lru/include/userver/multi_index_lru/container.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
#include <boost/intrusive/list_hook.hpp>
66
#include <boost/multi_index/hashed_index.hpp>
77
#include <boost/multi_index/mem_fun.hpp>
8+
#include <boost/multi_index/tag.hpp>
9+
#include <boost/multi_index/ordered_index.hpp>
10+
#include <boost/multi_index/member.hpp>
11+
#include <boost/multi_index_container.hpp>
812

913
#include <utility>
1014
#include <cstddef>
@@ -144,7 +148,7 @@ class LRUCacheContainer {
144148
void clear() {
145149
container.clear();
146150
}
147-
151+
148152
private:
149153
using CacheItem = impl::ValueWithHook<Value>;
150154
using List = boost::intrusive::list<

libraries/multi_index_lru/src/main_benchmark.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <vector>
77

88
#include <benchmark/benchmark.h>
9+
#include <boost/multi_index/member.hpp>
910

1011
USERVER_NAMESPACE_BEGIN
1112

@@ -26,7 +27,7 @@ struct User {
2627
bool operator==(const User& other) const { return id == other.id && email == other.email && name == other.name; }
2728
};
2829

29-
mamespace {
30+
namespace {
3031
User generateUser() {
3132
std::string email = "email" + std::to_string(utils::RandRange<int>(0, MAX_ID_SIZE));
3233
std::string name = "name" + std::to_string(utils::RandRange<int>(0, MAX_ID_SIZE));
@@ -42,14 +43,13 @@ std::string generateEmail() { return "email" + std::to_string(utils::RandRange<i
4243

4344
using UserCache = multi_index_lru::LRUCacheContainer<
4445
User,
45-
multi_index_lru::indexed_by<
46-
multi_index_lru::ordered_unique<multi_index_lru::tag<id_tag>, multi_index_lru::member<User, int, &User::id>>,
47-
multi_index_lru::
48-
ordered_unique<multi_index_lru::tag<email_tag>, multi_index_lru::member<User, std::string, &User::email>>,
49-
multi_index_lru::ordered_non_unique<
50-
multi_index_lru::tag<name_tag>,
51-
multi_index_lru::member<User, std::string, &User::name>>>,
52-
std::allocator<User>>;
46+
boost::multi_index::indexed_by<
47+
boost::multi_index::ordered_unique<boost::multi_index::tag<id_tag>, boost::multi_index::member<User, int, &User::id>>,
48+
boost::multi_index::
49+
ordered_unique<boost::multi_index::tag<email_tag>, boost::multi_index::member<User, std::string, &User::email>>,
50+
boost::multi_index::ordered_non_unique<
51+
boost::multi_index::tag<name_tag>,
52+
boost::multi_index::member<User, std::string, &User::name>>>>;
5353

5454
void LruFindEmplaceMix(benchmark::State& state) {
5555
const size_t size = state.range(0);
@@ -78,9 +78,9 @@ void LruFindEmplaceMix(benchmark::State& state) {
7878

7979
for ([[maybe_unused]] auto _ : state) {
8080
for (size_t i = 0; i < reading_operations_number; ++i) {
81-
cache.template find<name_tag, std::string>(names[i]);
82-
cache.template find<email_tag, std::string>(emails[i]);
83-
cache.template find<id_tag, int>(ids[i]);
81+
cache.find<name_tag, std::string>(names[i]);
82+
cache.find<email_tag, std::string>(emails[i]);
83+
cache.find<id_tag, int>(ids[i]);
8484
}
8585

8686
for (size_t i = 0; i < writing_operations_number; ++i) {
@@ -116,9 +116,9 @@ static void GetOperations(::benchmark::State& state) {
116116
state.ResumeTiming();
117117

118118
for (size_t i = 0; i < operations_count; ++i) {
119-
::benchmark::DoNotOptimize(cache.template find<name_tag, std::string>(names[i]));
120-
::benchmark::DoNotOptimize(cache.template find<email_tag, std::string>(emails[i]));
121-
::benchmark::DoNotOptimize(cache.template find<id_tag, int>(ids[i]));
119+
::benchmark::DoNotOptimize(cache.find<name_tag, std::string>(names[i]));
120+
::benchmark::DoNotOptimize(cache.find<email_tag, std::string>(emails[i]));
121+
::benchmark::DoNotOptimize(cache.find<id_tag, int>(ids[i]));
122122
}
123123
}
124124

libraries/multi_index_lru/src/main_test.cpp

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <string>
33

44
#include <gtest/gtest.h>
5+
#include <boost/multi_index/member.hpp>
6+
57
#include <userver/multi_index_lru/container.hpp>
68

79
using namespace USERVER_NAMESPACE;
@@ -27,8 +29,7 @@ class LRUUsersTest : public ::testing::Test {
2729
}
2830
};
2931

30-
template<template<typename, typename, typename> class LRUCacheContainer>
31-
using UserCache = LRUCacheContainer<
32+
using UserCache = multi_index_lru::LRUCacheContainer<
3233
User,
3334
boost::multi_index::indexed_by<
3435
boost::multi_index::ordered_unique<
@@ -40,14 +41,12 @@ class LRUUsersTest : public ::testing::Test {
4041
boost::multi_index::ordered_non_unique<
4142
boost::multi_index::tag<name_tag>,
4243
boost::multi_index::member<User, std::string, &User::name>>
43-
>,
44-
std::allocator<User>
44+
>
4545
>;
4646
};
4747

4848
TEST_F(LRUUsersTest, BasicOperations) {
49-
using MyCache = UserCache<multi_index_lru::LRUCacheContainer>;
50-
MyCache cache(3); // capacity == 3
49+
UserCache cache(3); // capacity == 3
5150

5251
// Test insertion
5352
cache.emplace(User{1, "alice@test.com", "Alice"});
@@ -77,8 +76,7 @@ TEST_F(LRUUsersTest, BasicOperations) {
7776
}
7877

7978
TEST_F(LRUUsersTest, LRUEviction) {
80-
using MyCache = UserCache<multi_index_lru::LRUCacheContainer>;
81-
MyCache cache(3);
79+
UserCache cache(3);
8280

8381
cache.emplace(User{1, "alice@test.com", "Alice"});
8482
cache.emplace(User{2, "bob@test.com", "Bob"});
@@ -112,8 +110,7 @@ class ProductsTest : public ::testing::Test {
112110
}
113111
};
114112

115-
template<template<typename, typename, typename> class LRUCacheContainer>
116-
using ProductCache = LRUCacheContainer<
113+
using ProductCache = multi_index_lru::LRUCacheContainer<
117114
Product,
118115
boost::multi_index::indexed_by<
119116
boost::multi_index::ordered_unique<
@@ -122,14 +119,12 @@ class ProductsTest : public ::testing::Test {
122119
boost::multi_index::ordered_unique<
123120
boost::multi_index::tag<name_tag>,
124121
boost::multi_index::member<Product, std::string, &Product::name>>
125-
>,
126-
std::allocator<Product>
122+
>
127123
>;
128124
};
129125

130126
TEST_F(ProductsTest, BasicProductOperations) {
131-
using MyCache = ProductCache<multi_index_lru::LRUCacheContainer>;
132-
MyCache cache(2);
127+
ProductCache cache(2);
133128

134129
cache.emplace(Product{"A1", "Laptop", 999.99});
135130
cache.emplace(Product{"A2", "Mouse", 29.99});
@@ -140,8 +135,7 @@ TEST_F(ProductsTest, BasicProductOperations) {
140135
}
141136

142137
TEST_F(ProductsTest, ProductEviction) {
143-
using MyCache = ProductCache<multi_index_lru::LRUCacheContainer>;
144-
MyCache cache(2);
138+
ProductCache cache(2);
145139

146140
cache.emplace(Product{"A1", "Laptop", 999.99});
147141
cache.emplace(Product{"A2", "Mouse", 29.99});

scripts/docs/en/userver/build/options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ userver is split into multiple CMake libraries.
2929
| `userver::ydb` | `USERVER_FEATURE_YDB` | `ydb` | @ref scripts/docs/en/userver/ydb.md |
3030
| `userver::otlp` | `USERVER_FEATURE_OTLP` | `otlp` | @ref opentelemetry "OpenTelemetry Protocol" |
3131
| `userver::s3api` | `USERVER_FEATURE_S3API` | `s3api` | @ref scripts/docs/en/userver/libraries/s3api.md |
32+
| `userver::multi_index_lru` | `USERVER_FEATURE_MULTI_INDEX_LRU` | `multi_index_lru` | @ref scripts/docs/en/userver/libraries/multi_index_lru.md |
3233
| `userver::easy` | `USERVER_FEATURE_EASY` | `easy` | @ref scripts/docs/en/userver/libraries/easy.md |
3334
| `userver::grpc-reflection` | `USERVER_FEATURE_GRPC_REFLECTION` | `grpc-reflection` | @ref scripts/docs/en/userver/libraries/grpc-reflection.md |
3435

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# LRU Container
2+
3+
## Introduction
4+
5+
Generic LRU (Least Recently Used) cache container implementation that combines Boost.MultiIndex for flexible indexing with Boost.Intrusive for efficient LRU tracking. It uses `namespace multi_index_lru`.
6+
7+
The container maintains elements in access order while supporting multiple indexing strategies through Boost.MultiIndex. The LRU eviction policy automatically removes the least recently accessed items when capacity is reached.
8+
9+
## Usage
10+
11+
```cpp
12+
#include <userver/utils/multi_index_lru.hpp>
13+
14+
using MyLruCache = multi_index_lru::LRUCacheContainer<
15+
MyValue,
16+
boost::multi_index::indexed_by<
17+
boost::multi_index::hashed_unique<
18+
boost::multi_index::tag<MyTag>,
19+
boost::multi_index::member<MyValue, std::string, &MyValue::key>
20+
>
21+
>
22+
>;
23+
24+
MyLruCache cache(1000); // Capacity of 1000 items
25+
cache.insert(my_value);
26+
auto it = cache.find<MyTag>("some_key");
27+
```

0 commit comments

Comments
 (0)