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 <functional>
7#include <optional>
8#include <string>
9#include <thread>
10#include <unordered_map>
11#include <utility>
12#include <vector>
13
14namespace xrpl {
15
16template <typename Key>
17static std::size_t
18extract(Key const& key)
19{
20 return key;
21}
22
23template <>
24inline std::size_t
26{
27 return ::beast::Uhash<>{}(key);
28}
29
30template <
31 typename Key,
32 typename Value,
33 typename Hash,
34 typename Pred = std::equal_to<Key>,
37{
39
40public:
41 using key_type = Key;
42 using mapped_type = Value;
46 using hasher = Hash;
47 using key_equal = Pred;
48 using allocator_type = Alloc;
52 using const_pointer = value_type const*;
55
56 struct Iterator
57 {
60 partition_map_type::iterator ait{};
61 map_type::iterator mit;
62
63 Iterator() = default;
64
66 {
67 }
68
70 operator*() const
71 {
72 return *mit;
73 }
74
76 operator->() const
77 {
78 return &(*mit);
79 }
80
81 void
83 {
84 ++mit;
85 while (mit == ait->end())
86 {
87 ++ait;
88 if (ait == map->end())
89 return;
90 mit = ait->begin();
91 }
92 }
93
94 // ++it
97 {
98 inc();
99 return *this;
100 }
101
102 // it++
105 {
106 Iterator tmp(*this);
107 inc();
108 return tmp;
109 }
110
111 friend bool
112 operator==(Iterator const& lhs, Iterator const& rhs)
113 {
114 return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
115 }
116
117 friend bool
118 operator!=(Iterator const& lhs, Iterator const& rhs)
119 {
120 return !(lhs == rhs);
121 }
122 };
123
125 {
127
129 partition_map_type::iterator ait{};
130 map_type::iterator mit;
131
132 ConstIterator() = default;
133
137
139 {
140 map = orig.map;
141 ait = orig.ait;
142 mit = orig.mit;
143 }
144
146 operator*() const
147 {
148 return *mit;
149 }
150
153 {
154 return &(*mit);
155 }
156
157 void
159 {
160 ++mit;
161 while (mit == ait->end())
162 {
163 ++ait;
164 if (ait == map->end())
165 return;
166 mit = ait->begin();
167 }
168 }
169
170 // ++it
173 {
174 inc();
175 return *this;
176 }
177
178 // it++
181 {
182 ConstIterator tmp(*this);
183 inc();
184 return tmp;
185 }
186
187 friend bool
188 operator==(ConstIterator const& lhs, ConstIterator const& rhs)
189 {
190 return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
191 }
192
193 friend bool
194 operator!=(ConstIterator const& lhs, ConstIterator const& rhs)
195 {
196 return !(lhs == rhs);
197 }
198 };
199
200private:
202 partitioner(Key const& key) const
203 {
204 return extract(key) % partitions_;
205 }
206
207 template <class T>
208 static void
209 end(T& it)
210 {
211 it.ait = it.map->end();
212 it.mit = it.map->back().end();
213 }
214
215 template <class T>
216 static void
217 begin(T& it)
218 {
219 for (it.ait = it.map->begin(); it.ait != it.map->end(); ++it.ait)
220 {
221 if (it.ait->begin() == it.ait->end())
222 continue;
223 it.mit = it.ait->begin();
224 return;
225 }
226 end(it);
227 }
228
229public:
231 {
232 // Set partitions to the number of hardware threads if the parameter
233 // is either empty or set to 0.
236 map_.resize(partitions_);
237 XRPL_ASSERT(
239 "xrpl::PartitionedUnorderedMap::PartitionedUnorderedMap : "
240 "nonzero partitions");
241 }
242
245 {
246 return partitions_;
247 }
248
251 {
252 return map_;
253 }
254
255 Iterator
257 {
258 Iterator it(&map_);
259 begin(it);
260 return it;
261 }
262
263 ConstIterator
264 cbegin() const
265 {
266 ConstIterator it(&map_);
267 begin(it);
268 return it;
269 }
270
271 ConstIterator
272 begin() const
273 {
274 return cbegin();
275 }
276
277 Iterator
279 {
280 Iterator it(&map_);
281 end(it);
282 return it;
283 }
284
285 ConstIterator
286 cend() const
287 {
288 ConstIterator it(&map_);
289 end(it);
290 return it;
291 }
292
293 ConstIterator
294 end() const
295 {
296 return cend();
297 }
298
299private:
300 template <class T>
301 void
302 find(key_type const& key, T& it) const
303 {
304 it.ait = it.map->begin() + partitioner(key);
305 it.mit = it.ait->find(key);
306 if (it.mit == it.ait->end())
307 end(it);
308 }
309
310public:
311 Iterator
312 find(key_type const& key)
313 {
314 Iterator it(&map_);
315 find(key, it);
316 return it;
317 }
318
319 ConstIterator
320 find(key_type const& key) const
321 {
322 ConstIterator it(&map_);
323 find(key, it);
324 return it;
325 }
326
327 template <class T, class U>
329 emplace(std::piecewise_construct_t const&, T&& keyTuple, U&& valueTuple)
330 {
331 auto const& key = std::get<0>(keyTuple);
332 Iterator it(&map_);
333 it.ait = it.map->begin() + partitioner(key);
334 auto [eit, inserted] = it.ait->emplace(
336 it.mit = eit;
337 return {it, inserted};
338 }
339
340 template <class T, class U>
342 emplace(T&& key, U&& val)
343 {
344 Iterator it(&map_);
345 it.ait = it.map->begin() + partitioner(key);
346 auto [eit, inserted] = it.ait->emplace(std::forward<T>(key), std::forward<U>(val));
347 it.mit = eit;
348 return {it, inserted};
349 }
350
351 void
353 {
354 for (auto& p : map_)
355 p.clear();
356 }
357
358 Iterator
359 erase(ConstIterator position)
360 {
361 Iterator it(&map_);
362 it.ait = position.ait;
363 it.mit = position.ait->erase(position.mit);
364
365 while (it.mit == it.ait->end())
366 {
367 ++it.ait;
368 if (it.ait == it.map->end())
369 break;
370 it.mit = it.ait->begin();
371 }
372
373 return it;
374 }
375
377 size() const
378 {
379 std::size_t ret = 0;
380 for (auto& p : map_)
381 ret += p.size();
382 return ret;
383 }
384
385 Value&
386 operator[](Key const& key)
387 {
388 return map_[partitioner(key)][key];
389 }
390
391private:
393};
394
395} // 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)
T hardware_concurrency(T... args)
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:655
T piecewise_construct
friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs)
friend bool operator!=(ConstIterator const &lhs, ConstIterator const &rhs)
friend bool operator==(Iterator const &lhs, Iterator const &rhs)
friend bool operator!=(Iterator const &lhs, Iterator const &rhs)