rippled
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 typename partition_map_type::iterator ait_;
61 typename map_type::iterator mit_;
62
63 iterator() = default;
64
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 typename partition_map_type::iterator ait_;
130 typename map_type::iterator mit_;
131
132 const_iterator() = 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 const_iterator tmp(*this);
183 inc();
184 return tmp;
185 }
186
187 friend bool
189 {
190 return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && lhs.mit_ == rhs.mit_;
191 }
192
193 friend bool
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 XRPL_ASSERT(
238 "xrpl::partitioned_unordered_map::partitioned_unordered_map : "
239 "nonzero partitions");
240 }
241
244 {
245 return partitions_;
246 }
247
250 {
251 return map_;
252 }
253
254 iterator
256 {
257 iterator it(&map_);
258 begin(it);
259 return it;
260 }
261
263 cbegin() const
264 {
265 const_iterator it(&map_);
266 begin(it);
267 return it;
268 }
269
271 begin() const
272 {
273 return cbegin();
274 }
275
276 iterator
278 {
279 iterator it(&map_);
280 end(it);
281 return it;
282 }
283
285 cend() const
286 {
287 const_iterator it(&map_);
288 end(it);
289 return it;
290 }
291
293 end() const
294 {
295 return cend();
296 }
297
298private:
299 template <class T>
300 void
301 find(key_type const& key, T& it) const
302 {
303 it.ait_ = it.map_->begin() + partitioner(key);
304 it.mit_ = it.ait_->find(key);
305 if (it.mit_ == it.ait_->end())
306 end(it);
307 }
308
309public:
310 iterator
311 find(key_type const& key)
312 {
313 iterator it(&map_);
314 find(key, it);
315 return it;
316 }
317
319 find(key_type const& key) const
320 {
321 const_iterator it(&map_);
322 find(key, it);
323 return it;
324 }
325
326 template <class T, class U>
328 emplace(std::piecewise_construct_t const&, T&& keyTuple, U&& valueTuple)
329 {
330 auto const& key = std::get<0>(keyTuple);
331 iterator it(&map_);
332 it.ait_ = it.map_->begin() + partitioner(key);
333 auto [eit, inserted] =
334 it.ait_->emplace(std::piecewise_construct, std::forward<T>(keyTuple), std::forward<U>(valueTuple));
335 it.mit_ = eit;
336 return {it, inserted};
337 }
338
339 template <class T, class U>
341 emplace(T&& key, U&& val)
342 {
343 iterator it(&map_);
344 it.ait_ = it.map_->begin() + partitioner(key);
345 auto [eit, inserted] = it.ait_->emplace(std::forward<T>(key), std::forward<U>(val));
346 it.mit_ = eit;
347 return {it, inserted};
348 }
349
350 void
352 {
353 for (auto& p : map_)
354 p.clear();
355 }
356
357 iterator
359 {
360 iterator it(&map_);
361 it.ait_ = position.ait_;
362 it.mit_ = position.ait_->erase(position.mit_);
363
364 while (it.mit_ == it.ait_->end())
365 {
366 ++it.ait_;
367 if (it.ait_ == it.map_->end())
368 break;
369 it.mit_ = it.ait_->begin();
370 }
371
372 return it;
373 }
374
376 size() const
377 {
378 std::size_t ret = 0;
379 for (auto& p : map_)
380 ret += p.size();
381 return ret;
382 }
383
384 Value&
385 operator[](Key const& key)
386 {
387 return map_[partitioner(key)][key];
388 }
389
390private:
392};
393
394} // namespace xrpl
T begin(T... args)
std::size_t partitioner(Key const &key) const
partitioned_unordered_map(std::optional< std::size_t > partitions=std::nullopt)
iterator erase(const_iterator position)
std::pair< iterator, bool > emplace(std::piecewise_construct_t const &, T &&keyTuple, U &&valueTuple)
std::pair< iterator, bool > emplace(T &&key, U &&val)
void find(key_type const &key, T &it) const
const_iterator find(key_type const &key) const
T end(T... args)
T hardware_concurrency(T... args)
T is_same_v
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:619
T piecewise_construct
T resize(T... args)
friend bool operator!=(const_iterator const &lhs, const_iterator const &rhs)
friend bool operator==(const_iterator const &lhs, const_iterator const &rhs)
friend bool operator!=(iterator const &lhs, iterator const &rhs)
friend bool operator==(iterator const &lhs, iterator const &rhs)