xrpld
Loading...
Searching...
No Matches
partitioned_unordered_map.h
1#pragma once
2
3#include <xrpl/beast/hash/uhash.h>
4#include <xrpl/beast/utility/instrumentation.h>
5
6#include <cstddef>
7#include <functional>
8#include <iterator>
9#include <memory>
10#include <optional>
11#include <string>
12#include <thread>
13#include <unordered_map>
14#include <utility>
15#include <vector>
16
17namespace xrpl {
18
19template <typename Key>
20static std::size_t
21extract(Key const& key)
22{
23 return key;
24}
25
26template <>
27inline std::size_t
29{
30 return ::beast::Uhash<>{}(key);
31}
32
33template <
34 typename Key,
35 typename Value,
36 typename Hash,
37 typename Pred = std::equal_to<Key>,
40{
42
43public:
44 using key_type = Key;
45 using mapped_type = Value;
49 using hasher = Hash;
50 using key_equal = Pred;
51 using allocator_type = Alloc;
55 using const_pointer = value_type const*;
58
59 struct Iterator
60 {
63 partition_map_type::iterator ait{};
64 map_type::iterator mit;
65
66 Iterator() = default;
67
69 {
70 }
71
73 operator*() const
74 {
75 return *mit;
76 }
77
79 operator->() const
80 {
81 return &(*mit);
82 }
83
84 void
86 {
87 ++mit;
88 while (mit == ait->end())
89 {
90 ++ait;
91 if (ait == map->end())
92 return;
93 mit = ait->begin();
94 }
95 }
96
97 // ++it
100 {
101 inc();
102 return *this;
103 }
104
105 // it++
108 {
109 Iterator tmp(*this);
110 inc();
111 return tmp;
112 }
113
114 friend bool
115 operator==(Iterator const& lhs, Iterator const& rhs)
116 {
117 return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
118 }
119 };
120
122 {
124
126 partition_map_type::iterator ait{};
127 map_type::iterator mit;
128
129 ConstIterator() = default;
130
134
135 ConstIterator(Iterator const& orig) : map(orig.map), ait(orig.ait), mit(orig.mit)
136 {
137 }
138
140 operator*() const
141 {
142 return *mit;
143 }
144
147 {
148 return &(*mit);
149 }
150
151 void
153 {
154 ++mit;
155 while (mit == ait->end())
156 {
157 ++ait;
158 if (ait == map->end())
159 return;
160 mit = ait->begin();
161 }
162 }
163
164 // ++it
167 {
168 inc();
169 return *this;
170 }
171
172 // it++
175 {
176 ConstIterator tmp(*this);
177 inc();
178 return tmp;
179 }
180
181 friend bool
182 operator==(ConstIterator const& lhs, ConstIterator const& rhs)
183 {
184 return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
185 }
186 };
187
188private:
190 partitioner(Key const& key) const
191 {
192 return extract(key) % partitions_;
193 }
194
195 template <class T>
196 static void
197 end(T& it)
198 {
199 it.ait = it.map->end();
200 it.mit = it.map->back().end();
201 }
202
203 template <class T>
204 static void
205 begin(T& it)
206 {
207 for (it.ait = it.map->begin(); it.ait != it.map->end(); ++it.ait)
208 {
209 if (it.ait->begin() == it.ait->end())
210 continue;
211 it.mit = it.ait->begin();
212 return;
213 }
214 end(it);
215 }
216
217public:
219 // Set partitions to the number of hardware threads if the parameter
220 // is either empty or set to 0.
221 : partitions_(
222 partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency())
223 {
224 map_.resize(partitions_);
225 XRPL_ASSERT(
227 "xrpl::PartitionedUnorderedMap::PartitionedUnorderedMap : "
228 "nonzero partitions");
229 }
230
233 {
234 return partitions_;
235 }
236
239 {
240 return map_;
241 }
242
243 Iterator
245 {
246 Iterator it(&map_);
247 begin(it);
248 return it;
249 }
250
251 ConstIterator
252 cbegin() const
253 {
254 ConstIterator it(&map_);
255 begin(it);
256 return it;
257 }
258
259 ConstIterator
260 begin() const
261 {
262 return cbegin();
263 }
264
265 Iterator
267 {
268 Iterator it(&map_);
269 end(it);
270 return it;
271 }
272
273 ConstIterator
274 cend() const
275 {
276 ConstIterator it(&map_);
277 end(it);
278 return it;
279 }
280
281 ConstIterator
282 end() const
283 {
284 return cend();
285 }
286
287private:
288 template <class T>
289 void
290 find(key_type const& key, T& it) const
291 {
292 it.ait = it.map->begin() + partitioner(key);
293 it.mit = it.ait->find(key);
294 if (it.mit == it.ait->end())
295 end(it);
296 }
297
298public:
299 Iterator
300 find(key_type const& key)
301 {
302 Iterator it(&map_);
303 find(key, it);
304 return it;
305 }
306
307 ConstIterator
308 find(key_type const& key) const
309 {
310 ConstIterator it(&map_);
311 find(key, it);
312 return it;
313 }
314
315 template <class T, class U>
317 emplace(std::piecewise_construct_t const&, T&& keyTuple, U&& valueTuple)
318 {
319 auto const& key = std::get<0>(keyTuple);
320 Iterator it(&map_);
321 it.ait = it.map->begin() + partitioner(key);
322 auto [eit, inserted] = it.ait->emplace(
324 it.mit = eit;
325 return {it, inserted};
326 }
327
328 template <class T, class U>
330 emplace(T&& key, U&& val)
331 {
332 Iterator it(&map_);
333 it.ait = it.map->begin() + partitioner(key);
334 auto [eit, inserted] = it.ait->emplace(std::forward<T>(key), std::forward<U>(val));
335 it.mit = eit;
336 return {it, inserted};
337 }
338
339 void
341 {
342 for (auto& p : map_)
343 p.clear();
344 }
345
346 Iterator
347 erase(ConstIterator position)
348 {
349 Iterator it(&map_);
350 it.ait = position.ait;
351 it.mit = position.ait->erase(position.mit);
352
353 while (it.mit == it.ait->end())
354 {
355 ++it.ait;
356 if (it.ait == it.map->end())
357 break;
358 it.mit = it.ait->begin();
359 }
360
361 return it;
362 }
363
365 size() const
366 {
367 std::size_t ret = 0;
368 for (auto& p : map_)
369 ret += p.size();
370 return ret;
371 }
372
373 Value&
374 operator[](Key const& key)
375 {
376 return map_[partitioner(key)][key];
377 }
378
379private:
381};
382
383} // namespace xrpl
T begin(T... args)
Iterator find(key_type const &key)
void find(key_type const &key, T &it) const
PartitionedUnorderedMap(std::optional< std::size_t > partitions=std::nullopt)
std::pair< Key const, mapped_type > value_type
Iterator erase(ConstIterator position)
std::size_t partitioner(Key const &key) const
std::unordered_map< key_type, mapped_type, hasher, key_equal, allocator_type > map_type
std::pair< Iterator, bool > emplace(std::piecewise_construct_t const &, T &&keyTuple, U &&valueTuple)
std::vector< map_type > partition_map_type
std::pair< Iterator, bool > emplace(T &&key, U &&val)
ConstIterator find(key_type const &key) const
T end(T... args)
T forward(T... args)
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::size_t extract(uint256 const &key)
Definition base_uint.h:673
T piecewise_construct
friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs)
friend bool operator==(Iterator const &lhs, Iterator const &rhs)