BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlcc_stripedunorderedmultimap.h
Go to the documentation of this file.
1/// @file bdlcc_stripedunorderedmultimap.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlcc_stripedunorderedmultimap.h -*-C++-*-
8#ifndef INCLUDED_BDLCC_STRIPEDUNORDEREDMULTIMAP
9#define INCLUDED_BDLCC_STRIPEDUNORDEREDMULTIMAP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlcc_stripedunorderedmultimap bdlcc_stripedunorderedmultimap
15/// @brief Provide a bucket-group locking (*striped*) unordered multimap.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlcc
19/// @{
20/// @addtogroup bdlcc_stripedunorderedmultimap
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlcc_stripedunorderedmultimap-purpose"> Purpose</a>
25/// * <a href="#bdlcc_stripedunorderedmultimap-classes"> Classes </a>
26/// * <a href="#bdlcc_stripedunorderedmultimap-description"> Description </a>
27/// * <a href="#bdlcc_stripedunorderedmultimap-thread-safety"> Thread Safety </a>
28/// * <a href="#bdlcc_stripedunorderedmultimap-runtime-complexity"> Runtime Complexity </a>
29/// * <a href="#bdlcc_stripedunorderedmultimap-number-of-stripes"> Number of Stripes </a>
30/// * <a href="#bdlcc_stripedunorderedmultimap-set-vs-insert-methods"> Set vs. Insert Methods </a>
31/// * <a href="#bdlcc_stripedunorderedmultimap-rehash"> Rehash </a>
32/// * <a href="#bdlcc_stripedunorderedmultimap-concurrent-rehash"> Concurrent Rehash </a>
33/// * <a href="#bdlcc_stripedunorderedmultimap-rehash-control"> Rehash Control </a>
34/// * <a href="#bdlcc_stripedunorderedmultimap-usage"> Usage </a>
35/// * <a href="#bdlcc_stripedunorderedmultimap-example-1-basic-usage"> Example 1: Basic Usage </a>
36///
37/// # Purpose {#bdlcc_stripedunorderedmultimap-purpose}
38/// Provide a bucket-group locking (*striped*) unordered multimap.
39///
40/// # Classes {#bdlcc_stripedunorderedmultimap-classes}
41///
42/// - bdlcc::StripedUnorderedMultiMap: Striped hash multimap
43///
44/// @see bdlcc_stripedunorderedmap, bdlcc_stripedunorderedimpl
45///
46/// # Description {#bdlcc_stripedunorderedmultimap-description}
47/// This component provides a single concurrent (fully thread-safe)
48/// associative container, `bdlcc::StripedUnorderedMultiMap`, that partitions
49/// the underlying hash table into a (user defined) number of "bucket groups"
50/// and controls access to each bucket group by a separate read-write lock.
51/// This design allows greater concurrency (and improved performance) than a
52/// `bsl::unordered_multimap` object protected by a single lock.
53///
54/// `bdlcc::StripedUnorderedMultiMap` differs from `bdlcc::StripedUnorderedMap`
55/// in that the former allows multiple elements to have the same key value but
56/// the later requires that each element have a unique key value. Methods of
57/// the two classes have similar names and semantics differing only where the
58/// different key policy pertains.
59///
60/// The terms "bucket", "load factor", and "rehash" have the same meaning as
61/// they do in the @ref bslstl_unorderedmultimap component (see
62/// {@ref bslstl_unorderedmultimap |Unordered Multimap Configuration}). A general
63/// introduction to these ideas can be found at:
64/// https://en.wikipedia.org/wiki/Hash_table
65///
66/// `bdlcc::StripedUnorderedMultiMap` (and concurrent containers in general)
67/// does not provide iterators that allow users to manipulate or traverse the
68/// values of elements in a map. Alternatively, this container provides the
69/// `setComputedValue*` methods that allows users to change the value for a
70/// given key via a user provided functor and the `visit` method that will apply
71/// a user provided functor the value of every key in the map.
72///
73/// The `bdlcc::StripedUnorderedMultiMap` class is an *irregular* value-semantic
74/// type, even if `KEY` and `VALUE` are VSTs. This class does not implement
75/// equality comparison, assignment operator, or copy constructor.
76///
77/// ## Thread Safety {#bdlcc_stripedunorderedmultimap-thread-safety}
78///
79///
80/// The `bdlcc::StripedUnorderedMultiMap` class template is fully thread-safe
81/// (see {@ref bsldoc_glossary |Fully Thread-Safe}), assuming that the allocator is
82/// fully thread-safe. Each method is executed by the calling thread.
83///
84/// ## Runtime Complexity {#bdlcc_stripedunorderedmultimap-runtime-complexity}
85///
86///
87/// @code
88/// +----------------------------------------------------+--------------------+
89/// | Operation | Complexity |
90/// +====================================================+====================+
91/// | insert, setValueFirst, setValueAll, | Average: O[1] |
92/// | setComputedValueAll, setComputedValueFirst, update| Worst: O[n] |
93/// +----------------------------------------------------+--------------------+
94/// | eraseFirst, eraseAll, getValueFirst, getValueAll | Average: O[1] |
95/// | | Worst: O[n] |
96/// +----------------------------------------------------+--------------------+
97/// | visit(key, visitor) | Average: O[1] |
98/// | visitReadOnly(key, visitor) | Worst: O[n] |
99/// +----------------------------------------------------+--------------------+
100/// | insertBulk, k elements | Average: O[k] |
101/// | | Worst: O[n*k] |
102/// +----------------------------------------------------+--------------------+
103/// | examine | Average: O[1] |
104/// | | Worst: O[n] |
105/// +----------------------------------------------------+--------------------+
106/// | eraseBulkAll, k elements | Average: O[k] |
107/// | | Worst: O[n*k] |
108/// +----------------------------------------------------+--------------------+
109/// | rehash | O[n] |
110/// +----------------------------------------------------+--------------------+
111/// | visit(visitor), visitReadOnly(visitor) | O[n] |
112/// +----------------------------------------------------+--------------------+
113/// @endcode
114///
115/// ## Number of Stripes {#bdlcc_stripedunorderedmultimap-number-of-stripes}
116///
117///
118/// Performance improves monotonically when the number of stripes increases.
119/// However, the rate of improvement decreases, and reaches a plateau. The
120/// plateau is reached roughly at four times the number of the threads
121/// *concurrently* using the hash map.
122///
123/// ## Set vs. Insert Methods {#bdlcc_stripedunorderedmultimap-set-vs-insert-methods}
124///
125///
126/// This container provides several `set*` methods and similarly named `insert*`
127/// methods that have nearly identical semantics. Both update the value of an
128/// existing element and both add a new element if the element sought is not
129/// present. Conceptually, the emphasis of the `set*` methods is the former, so
130/// its return value is the number of elements updated, and the intent of
131/// `insert*` methods is to add elements, so its return value is the number of
132/// new elements.
133///
134/// ## Rehash {#bdlcc_stripedunorderedmultimap-rehash}
135///
136///
137///
138/// ### Concurrent Rehash {#bdlcc_stripedunorderedmultimap-concurrent-rehash}
139///
140///
141/// A rehash operation is a re-organization of the hash map to a different
142/// number of buckets. This is a heavy operation that interferes with, but does
143/// *not* disallow, other operations on the container. Rehash is warranted when
144/// the current load factor exceeds the current maximum allowed load factor.
145/// Expressed explicitly:
146/// @code
147/// bucketCount() <= maxLoadFactor() * size();
148/// @endcode
149/// This above condition is tested implicitly by several methods and if found
150/// true (and if rehash is enabled and rehash is not underway), a rehash is
151/// started. The methods that check the load factor are:
152///
153/// * All methods that insert elements (i.e., increase `size()`).
154/// * The `maxLoadFactor(newMaxLoadFactor)` method.
155/// * The `rehash` method.
156///
157/// ### Rehash Control {#bdlcc_stripedunorderedmultimap-rehash-control}
158///
159///
160/// `enableRehash` and `disableRehash` methods are provided to control the
161/// rehash enable flag. Note that disabling rehash does not impact a rehash in
162/// progress.
163///
164/// ## Usage {#bdlcc_stripedunorderedmultimap-usage}
165///
166///
167/// In this section we show intended use of this component.
168///
169/// ### Example 1: Basic Usage {#bdlcc_stripedunorderedmultimap-example-1-basic-usage}
170///
171///
172/// This example shows some basic usage of `bdlcc::StripedUnorderedMultiMap`.
173///
174/// First, we define a `bdlcc::StripedUnorderedMultiMap` object, `myFriends`,
175/// that maps `int` to `bsl::string`:
176/// @code
177/// bdlcc::StripedUnorderedMultiMap<int, bsl::string> myFriends;
178/// @endcode
179/// Notice that we are using the default value number of buckets, number of
180/// stripes, and allocator.
181///
182/// Then, we insert three elements into the map and verify that the size is the
183/// expected value:
184/// @code
185/// assert(0 == myFriends.size());
186/// myFriends.insert(0, "Alex");
187/// myFriends.insert(1, "John");
188/// myFriends.insert(2, "Rob");
189/// assert(3 == myFriends.size());
190/// @endcode
191/// Next, we demonstrate `insertBulk` by creating a vector of three key-value
192/// pairs and add them to the map using a single method call:
193/// @code
194/// typedef bsl::pair<int, bsl::string> PairType;
195/// bsl::vector<PairType> insertData;
196/// insertData.push_back(PairType(3, "Jim"));
197/// insertData.push_back(PairType(4, "Jeff"));
198/// insertData.push_back(PairType(5, "Ian" ));
199/// assert(3 == insertData.size())
200///
201/// assert(3 == myFriends.size());
202/// myFriends.insertBulk(insertData.begin(), insertData.end());
203/// assert(6 == myFriends.size());
204/// @endcode
205/// Then, we use `getValueFirst` method to retrieve the previously inserted
206/// string associated with the value 1:
207/// @code
208/// bsl::string value;
209/// bsl::size_t rc = myFriends.getValueFirst(&value, 1);
210/// assert(1 == rc);
211/// assert("John" == value);
212/// @endcode
213/// Now, we insert two additional elements, each having key values that already
214/// appear in the hash map:
215/// @code
216/// myFriends.insert(3, "Steve");
217/// assert(7 == myFriends.size());
218///
219/// myFriends.insert(4, "Tim");
220/// assert(8 == myFriends.size());
221/// @endcode
222/// Finally, we use the `getValueAll` method to retrieve both values associated
223/// with the key 3:
224/// @code
225/// bsl::vector<bsl::string> values;
226/// rc = myFriends.getValueAll(&values, 3);
227/// assert(2 == rc);
228///
229/// assert(2 == values.size());
230/// assert(values.end() != bsl::find(values.begin(), values.end(), "Jim"));
231/// assert(values.end() != bsl::find(values.begin(), values.end(), "Steve"));
232/// @endcode
233/// Notice that the results have the expected number and values. Also notice
234/// that we must search the results for the expected values because the order in
235/// which values are retrieved is not specified.
236/// @}
237/** @} */
238/** @} */
239
240/** @addtogroup bdl
241 * @{
242 */
243/** @addtogroup bdlcc
244 * @{
245 */
246/** @addtogroup bdlcc_stripedunorderedmultimap
247 * @{
248 */
249
250#include <bdlscm_version.h>
251
253
254#include <bslmf_movableref.h>
255
256#include <bsls_assert.h>
257#include <bsls_libraryfeatures.h>
258
259#include <bsl_functional.h>
260
261#include <vector>
262
263
264namespace bdlcc {
265
266 // ==============================
267 // class StripedUnorderedMultiMap
268 // ==============================
269
270/// This class template defines a fully thread-safe container that provides
271/// a mapping from keys (of template parameter type `KEY`) to their
272/// associated mapped values (of template parameter type `VALUE`).
273///
274/// The buckets of this hash map are guarded by `numStripes` reader-writer
275/// locks, a value specified on construction. Partitioning the buckets
276/// among several locks allows greater overall concurrency than a
277/// `bsl::unordered_multimap` object guarded by a single lock.
278///
279/// The interface is inspired by, but not identical to that of
280/// `bsl::unordered_multimap`. Notably absent are iterators, which are of
281/// limited practicality in the typical use case because they are readily
282/// invalidated when the map population is open to modification by multiple
283/// threads.
284///
285/// See @ref bdlcc_stripedunorderedmultimap
286template <class KEY,
287 class VALUE,
288 class HASH = bsl::hash<KEY>,
289 class EQUAL = bsl::equal_to<KEY> >
291
292 private:
293 // PRIVATE TYPES
295
296 // DATA
297
298 // implementation of the striped hash map
299 Impl d_imp;
300
301 private:
302 // NOT IMPLEMENTED
305 // = delete
308 // = delete
309
310 public:
311 // PUBLIC CONSTANTS
312 enum {
313 k_DEFAULT_NUM_BUCKETS = 16, // Default number of buckets
314 k_DEFAULT_NUM_STRIPES = 4 // Default number of stripes
315 };
316
317 // PUBLIC TYPES
318
319 /// Value type of a bulk insert entry.
321
322 /// An alias to a function meeting the following contract:
323 /// @code
324 /// /// Visit the specified `value` attribute associated with the
325 /// /// specified `key`. Return `true` if this function may be
326 /// /// called on additional elements, and `false` otherwise (i.e., /// if no other elements should be visited).
327 ///
328 /// \note Note that this
329 /// /// functor can change the value associated with `key`.
330 /// bool visitorFunction(VALUE *value, const KEY& key);
331 /// @endcode
332 typedef bsl::function<bool (VALUE *, const KEY&)> VisitorFunction;
333
334 /// An alias to a function meeting the following contract:
335 /// @code
336 /// /// Visit the specified `value` attribute associated with the
337 /// /// specified `key`. Return `true` if this function may be
338 /// /// called on additional elements, and `false` otherwise (i.e., /// if no other elements should be visited).
339 ///
340 /// \note Note that this
341 /// /// functor can *not* change the values associated with `key`
342 /// /// and `value`.
343 /// bool readOnlyVisitorFunction(const VALUE& value, const KEY& key);
344 /// @endcode
345 typedef bsl::function<bool (const VALUE&, const KEY&)>
347
348 /// An alias to a function meeting the following contract:
349 /// @code
350 /// /// Return `true` if the specified `value` is to be removed from /// the container, and `false` otherwise.
351 ///
352 /// \note Note that this
353 /// /// functor can *not* change the values associated with `value`.
354 /// bool eraseIfValuePredicate(const VALUE& value);
355 /// @endcode
356 typedef bsl::function<bool(const VALUE&)> EraseIfValuePredicate;
357
358 // CREATORS
359
360 /// Create an empty `StripedUnorderedMultiMap` object, a fully
361 /// thread-safe hash map where access is partitioned into "stripes" (a
362 /// group of buckets protected a reader-writer mutex). Optionally
363 /// specify `numInitialBuckets` and `numStripes` which define the
364 /// minimum number of buckets and the (fixed) number of stripes in this
365 /// map. Optionally specify a `basicAllocator` used to supply memory.
366 /// If `basicAllocator` is 0, the currently installed default allocator is used. The hash map has rehash enabled.
367 ///
368 /// \note Note that the number of
369 /// stripes will not change after construction, but the number of
370 /// buckets may (unless rehashing is disabled via `disableRehash`).
372 bsl::size_t numInitialBuckets = k_DEFAULT_NUM_BUCKETS,
373 bsl::size_t numStripes = k_DEFAULT_NUM_STRIPES,
374 bslma::Allocator *basicAllocator = 0);
376 bslma::Allocator *basicAllocator);
377
379 // Destroy this hash map.
380
381 // MANIPULATORS
382
383 /// Remove all elements from this hash map. If rehash is in progress,
384 /// block until it completes.
385 void clear();
386
387 /// Prevent future rehash until `enableRehash` is called.
388 void disableRehash();
389
390 /// Allow rehash. If conditions warrant, rehash will be started by the
391 /// *next* method call that observes the load factor is exceeded (see {Concurrent Rehash}).
392 ///
393 /// \note Note that calling
394 /// `maxLoadFactor(maxLoadFactor())` (i.e., setting the maximum load
395 /// factor to its current value) will trigger a rehash if needed but
396 /// otherwise does not change the hash map.
397 void enableRehash();
398
399 /// Erase from this hash map the elements having the specified `key`.
400 /// Return the number of elements erased.
401 bsl::size_t eraseAll(const KEY& key);
402
403 /// Erase from this hash map the elements having the specified `key` for
404 /// which the specified `predicate` holds true. Return the number of
405 /// elements erased.
406 bsl::size_t eraseAllIf(const KEY& key,
407 const EraseIfValuePredicate& predicate);
408
409 /// Erase from this hash map elements in this hash map having any of the
410 /// values in the keys contained between the specified `first`
411 /// (inclusive) and `last` (exclusive) random-access iterators. The
412 /// iterators provide read access to a sequence of `KEY` objects. All
413 /// erasures are done by the calling thread and the order of erasure is
414 /// not specified. Return the number of elements removed.
415 ///
416 /// \pre The behavior is undefined unless `first <= last`.
417 /// \note Note that the map may not have
418 /// an element for every value in `keys`.
419 template <class RANDOM_ITER>
420 bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last);
421
422 /// Erase from this hash map the *first* element (of possibly many)
423 /// found to the specified `key`. Return the number of elements erased.
424 ///
425 /// \note Note that method is more performant than `eraseAll` when there is
426 /// one element having `key`.
427 bsl::size_t eraseFirst(const KEY& key);
428
429 /// Erase from this hash map the *first* element (of possibly many) with
430 /// specified `key` found, for which the specified `predicate` holds
431 /// true. Return the number of elements erased.
432 bsl::size_t eraseFirstIf(const KEY& key,
433 const EraseIfValuePredicate& predicate);
434
435 /// Insert into this hash map an element having the specified `key` and `value`.
436 ///
437 /// \note Note that other elements having the same `key` may exist
438 /// in this hash map.
439 void insert(const KEY& key, const VALUE& value);
440
441 /// Insert into this hash map an element having the specified `key` and
442 /// the specified move-insertable `value`. The `value` object is left
443 /// in a valid but unspecified state. If `value` is allocator-enabled
444 /// and `allocator() != value.allocator()` this operation may cost as much as a copy.
445 ///
446 /// \note Note that other elements having the same `key` may
447 /// exist in this hash map.
448 void insert(const KEY& key, bslmf::MovableRef<VALUE> value);
449
450 /// Insert into this hash map elements having the key-value pairs
451 /// obtained between the specified `first` (inclusive) and `last`
452 /// (exclusive) random-access iterators. The iterators provide read
453 /// access to a sequence of `bsl::pair<KEY, VALUE>` objects. All
454 /// insertions are done by the calling thread and the order of insertion is not specified.
455 ///
456 /// \pre The behavior is undefined unless `first <= last`.
457 template <class RANDOM_ITER>
458 void insertBulk(RANDOM_ITER first, RANDOM_ITER last);
459
460 /// Recreate this hash map to one having at least the specified
461 /// `numBuckets`. This operation is a no-op if *any* of the following
462 /// are true: 1) rehash is disabled; 2) `numBuckets` less or equals the
463 /// current number of buckets. See {Rehash}.
464 void rehash(bsl::size_t numBuckets);
465
466 /// Serially invoke the specified `visitor` passing the specified `key`,
467 /// and the address of the value of each element in this hash map having
468 /// `key`. If `key` is not in the map, `value` will be default
469 /// constructed. That is, for each `(key, value)` found, invoke:
470 /// @code
471 /// bool visitor(VALUE *value, const Key& key);
472 /// @endcode
473 /// If no element in the map has `key`, insert `(key, VALUE())` and
474 /// invoke `visitor` with `value` pointing to the default constructed
475 /// value. Return the number of elements visited or the negation of
476 /// that value if visitations stopped because `visitor` returned
477 /// `false`. `visitor`, when invoked, has exclusive access (i.e., write
478 /// access) to each element during each invocation.
479 ///
480 /// \pre The behavior is undefined if hash map manipulators and `getValue*` methods are
481 /// invoked from within `visitor`, as it may lead to a deadlock.
482 ///
483 /// \note Note that the `setComputedValueFirst` method is more performant than the
484 /// when the hash map contains a single element for `key`. Also note
485 /// that a return value of `0` implies that an element was inserted.
486 int setComputedValueAll(const KEY& key,
487 const VisitorFunction& visitor);
488
489 /// Invoke the specified `visitor` passing the specified `key`, and the
490 /// address of the value attribute of the *first* element (of possibly
491 /// many elements) found in this hash map having `key`. If `key` is not
492 /// in the map, `value` will be default constructed. That is, for
493 /// `(key, value)`, invoke:
494 /// @code
495 /// bool visitor(VALUE *value, const Key& key);
496 /// @endcode
497 /// If no element in the map has `key`, insert `(key, VALUE())` and
498 /// invoke `visitor` with `value` pointing to the default constructed
499 /// value. Return 1 if `key` was found and `visitor` returned `true`, 0
500 /// if `key` was not found, and -1 if `key` was found and `visitor`
501 /// returned `false`. `visitor`, when invoked, has exclusive access (i.e., write access) to the element.
502 ///
503 /// \pre The behavior is undefined if
504 /// hash map manipulators and `getValue*` methods are invoked from within `visitor`, as it may lead to a deadlock.
505 ///
506 /// \note Note that the
507 /// return value equals the number of elements inserted. Also note
508 /// that, when there are multiple elements having `key`, the selection
509 /// of "first" is implementation specific and subject to change. Also
510 /// note that this method is more performant than the
511 /// `setComputedValueAll` method when the hash map contains a single
512 /// element for `key`. Also note that a return value of `0` implies
513 /// that an element was inserted.
514 int setComputedValueFirst(const KEY& key,
515 const VisitorFunction& visitor);
516
517 /// Set the value attribute of every element in this hash map having the
518 /// specified `key` to the specified `value`. If no such such element
519 /// exists, insert `(key, value)`. Return the number of elements found with `key`.
520 ///
521 /// \note Note that if no elements were found, and a new value
522 /// was inserted, `0` is returned.
523 bsl::size_t setValueAll(const KEY& key, const VALUE& value);
524
525 /// Set the value attribute of the *first* element in this hash map (of
526 /// possibly many) found to have the specified `key` to the specified
527 /// `value`. If no such such element exists, insert `(key, value)`. Return the number of elements found with `key`.
528 ///
529 /// \note Note that if no
530 /// elements were found, and a new value was inserted, `0` is returned.
531 /// Also note that this method is more performant than `setValueAll`
532 /// when there is one element having `key` in the hash map.
533 bsl::size_t setValueFirst(const KEY& key, const VALUE& value);
534
535 /// Set the value attribute of the *first* element in this hash map (of
536 /// possibly many) found to have the specified `key` to the specified
537 /// move-insertable `value`. If no such such element exists, insert
538 /// `(key, value)`. Return the number of elements found with `key`.
539 /// The `value` object is left in a valid but unspecified state. If
540 /// `value` is allocator-enabled and `allocator() != value.allocator()` this operation may cost as much as a copy.
541 ///
542 /// \note Note that if no elements
543 /// were found, and a new value was inserted, `0` is returned. Also
544 /// note that this method is more performant than `setValueAll` when
545 /// there is one element having `key` in the hash map.
546 bsl::size_t setValueFirst(const KEY& key, bslmf::MovableRef<VALUE> value);
547
548 /// Serially call the specified `visitor` on each element (if one
549 /// exists) in this hash map having the specified `key` until every such
550 /// element has been updated or `visitor` returns `false`. That is, for
551 /// `(key, value)`, invoke:
552 /// @code
553 /// bool visitor(&value, key);
554 /// @endcode
555 /// Return the number of elements visited or the negation of that value
556 /// if visitations stopped because `visitor` returned `false`.
557 /// `visitor` has exclusive access (i.e., write access) to each element for duration of each invocation.
558 ///
559 /// \pre The behavior is undefined if hash
560 /// map manipulators and `getValue*` methods are invoked from within
561 /// `visitor`, as it may lead to a deadlock.
562 ///
563 /// @deprecated Use @ref visit(key, visitor) instead.
564 int update(const KEY& key, const VisitorFunction& visitor);
565
566 /// Call the specified `visitor` (in an unspecified order) on the
567 /// elements in this hash table until each such element has been visited
568 /// or `visitor` returns `false`. That is, for `(key, value)`, invoke:
569 /// @code
570 /// bool visitor(&value, key);
571 /// @endcode
572 /// Return the number of elements visited or the negation of that value
573 /// if visitations stopped because `visitor` returned `false`.
574 /// `visitor` has exclusive access (i.e., write access) to each element
575 /// for duration of each invocation. Every element present in this hash
576 /// map at the time `visit` is invoked will be visited unless it is
577 /// removed before `visitor` is called for that element. Each
578 /// visitation is done by the calling thread and the order of visitation
579 /// is not specified. Elements inserted during the execution of `visit` may or may not be visited.
580 ///
581 /// \pre The behavior is undefined if hash map
582 /// manipulators and `getValue*` methods are invoked from within `visitor`, as it may lead to a deadlock.
583 ///
584 /// \note Note that `visitor` can
585 /// change the value of the visited elements.
586 int visit(const VisitorFunction& visitor);
587
588 /// Serially call the specified `visitor` on each element (if one
589 /// exists) in this hash map having the specified `key` until every such
590 /// element has been updated or `visitor` returns `false`. That is, for
591 /// `(key, value)`, invoke:
592 /// @code
593 /// bool visitor(&value, key);
594 /// @endcode
595 /// Return the number of elements visited or the negation of that value
596 /// if visitations stopped because `visitor` returned `false`.
597 /// `visitor` has exclusive access (i.e., write access) to each element for duration of each invocation.
598 ///
599 /// \pre The behavior is undefined if hash
600 /// map manipulators and `getValue*` methods are invoked from within
601 /// `visitor`, as it may lead to a deadlock.
602 int visit(const KEY& key, const VisitorFunction& visitor);
603
604 // ACCESSORS
605
606 /// Return the number of buckets in the array of buckets maintained by this hash map.
607 ///
608 /// \note Note that unless rehash is disabled, the value
609 /// returned may be obsolete by the time it is received.
610 bsl::size_t bucketCount() const;
611
612 /// Return the index of the bucket, in the array of buckets maintained
613 /// by this hash map, where elements having the specified `key` are inserted.
614 ///
615 /// \note Note that unless rehash is disabled, the value returned
616 /// may be obsolete at the time it is returned.
617 bsl::size_t bucketIndex(const KEY& key) const;
618
619 /// Return the number of elements contained in the bucket at the
620 /// specified `index` in the array of buckets maintained by this hash map.
621 ///
622 /// \pre The behavior is undefined unless `0 <= index < bucketCount()`.
623 ///
624 /// \note Note that unless rehash is disabled
625 /// the value returned may be obsolete by the time it is returned.
626 bsl::size_t bucketSize(bsl::size_t index) const;
627
628 /// Return `true` if this hash map contains no elements, and `false`
629 /// otherwise.
630 bool empty() const;
631
632 /// Return (a copy of) the key-equality functor used by this hash map.
633 /// The returned function will return `true` if two `KEY` objects have
634 /// the same value, and `false` otherwise.
635 EQUAL equalFunction() const;
636
637 bsl::size_t getValueAll(bsl::vector<VALUE> *valuesPtr,
638 const KEY& key) const;
639 bsl::size_t getValueAll(std::vector<VALUE> *valuesPtr,
640 const KEY& key) const;
641#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
642 /// Load, into the specified `*valuesPtr`, the value attributes of every
643 /// element in this hash map having the specified `key`. Return the number of elements found with `key`.
644 ///
645 /// \note Note that the order of the
646 /// values returned is not specified.
647 bsl::size_t getValueAll(std::pmr::vector<VALUE> *valuesPtr,
648 const KEY& key) const;
649#endif
650
651 /// Load, into the specified `*value`, the value attribute of the first
652 /// element found in this hash map having the specified `key`. Return 1
653 /// on success, and 0 if `key` does not exist in this hash map.
654 ///
655 /// \note Note that the return value equals the number of values returned.
656 bsl::size_t getValueFirst(VALUE *value, const KEY& key) const;
657
658 /// Return (a copy of) the unary hash functor used by this hash map.
659 /// The return function will generate a hash value (of type
660 /// `std::size_t`) for a `KEY` object.
661 HASH hashFunction() const;
662
663 /// Return `true` if rehash is enabled, or `false` otherwise.
664 bool isRehashEnabled() const;
665
666 /// Return the current quotient of the size of this hash map and the number of buckets.
667 ///
668 /// \note Note that the load factor is a measure of
669 /// container "fullness"; that is, a high load factor typically implies
670 /// many collisions (many elements landing in the same bucket) and that
671 /// decreases performance. See {Rehash Control}.
672 float loadFactor() const;
673
674 /// Return the maximum load factor allowed for this hash map. If an
675 /// insert operation would cause the load factor to exceed the
676 /// `maxLoadFactor()` and rehashing is enabled, then that insert
677 /// increases the number of buckets and rehashes the elements of the
678 /// container into that larger set of buckets. See {Rehash Control}.
679 float maxLoadFactor() const;
680
681 /// Return the number of stripes in the hash.
682 bsl::size_t numStripes() const;
683
684 /// Call the specified `visitor` (in an unspecified order) on the
685 /// elements in this hash table until each such element has been visited
686 /// or `visitor` returns `false`. That is, for `(key, value)`, invoke:
687 /// @code
688 /// bool visitor(value, key);
689 /// @endcode
690 /// Return the number of elements visited or the negation of that value
691 /// if visitations stopped because `visitor` returned `false`.
692 /// `visitor` has read-only access to each element for duration of each
693 /// invocation. Every element present in this hash map at the time
694 /// `visit` is invoked will be visited unless it is removed before
695 /// `visitor` is called for that element. Each visitation is done by
696 /// the calling thread and the order of visitation is not specified.
697 ///
698 /// \pre The behavior is undefined if hash map manipulators are invoked from within `visitor`, as it may lead to a deadlock.
699 ///
700 /// \note Note that `visitor`
701 /// can *not* change the value of the visited elements.
702 int visitReadOnly(const ReadOnlyVisitorFunction& visitor) const;
703
704 /// Serially call the specified `visitor` on each element (if one
705 /// exists) in this hash map having the specified `key` until every such
706 /// element has been visited or `visitor` returns `false`. That is, for
707 /// `(key, value)`, invoke:
708 /// @code
709 /// bool visitor(value, key);
710 /// @endcode
711 /// Return the number of elements visited or the negation of that value
712 /// if visitations stopped because `visitor` returned `false`.
713 /// `visitor` has read-only access to each element for duration of each invocation.
714 ///
715 /// \pre The behavior is undefined if hash map manipulators are
716 /// invoked from within `visitor`, as it may lead to a deadlock.
717 int visitReadOnly(const KEY& key,
718 const ReadOnlyVisitorFunction& visitor) const;
719
720 /// Return the current number of elements in this hash map.
721 bsl::size_t size() const;
722
723 // Aspects
724
725 /// Return the allocator used by this hash map to supply memory.
726 ///
727 /// \note Note that if no allocator was supplied at construction the default
728 /// allocator installed at that time is used.
730};
731
732// ============================================================================
733// INLINE DEFINITIONS
734// ============================================================================
735
736 // ------------------------------
737 // class StripedUnorderedMultiMap
738 // ------------------------------
739
740// CREATORS
741template <class KEY, class VALUE, class HASH, class EQUAL>
742inline
744 bsl::size_t numInitialBuckets,
745 bsl::size_t numStripes,
746 bslma::Allocator *basicAllocator)
747: d_imp(numInitialBuckets, numStripes, basicAllocator)
748{
749}
750
751template <class KEY, class VALUE, class HASH, class EQUAL>
752inline
754 bslma::Allocator *basicAllocator)
755: d_imp(k_DEFAULT_NUM_BUCKETS, k_DEFAULT_NUM_STRIPES, basicAllocator)
756{
757}
758
759// MANIPULATORS
760template <class KEY, class VALUE, class HASH, class EQUAL>
761inline
766
767template <class KEY, class VALUE, class HASH, class EQUAL>
768inline
773
774template <class KEY, class VALUE, class HASH, class EQUAL>
775inline
780
781template <class KEY, class VALUE, class HASH, class EQUAL>
782inline
784 const KEY& key)
785{
786 return d_imp.eraseAll(key);
787}
788
789template <class KEY, class VALUE, class HASH, class EQUAL>
790inline
792 const KEY& key,
793 const EraseIfValuePredicate& predicate)
794{
795 return d_imp.eraseAllIf(key, predicate);
796}
797
798template <class KEY, class VALUE, class HASH, class EQUAL>
799template <class RANDOM_ITER>
800inline
802 RANDOM_ITER first,
803 RANDOM_ITER last)
804{
805 BSLS_ASSERT(first <= last);
806
807 return d_imp.eraseBulkAll(first, last);
808}
809
810template <class KEY, class VALUE, class HASH, class EQUAL>
811inline
813 const KEY& key)
814{
815 return d_imp.eraseFirst(key);
816}
817
818template <class KEY, class VALUE, class HASH, class EQUAL>
819inline
820bsl::size_t
822 const KEY& key,
823 const EraseIfValuePredicate& predicate)
824{
825 return d_imp.eraseFirstIf(key, predicate);
826}
827
828template <class KEY, class VALUE, class HASH, class EQUAL>
829inline
831 const KEY& key,
832 const VALUE& value)
833{
834 d_imp.insertAlways(key, value);
835}
836
837template <class KEY, class VALUE, class HASH, class EQUAL>
838inline
840 const KEY& key,
842{
843 d_imp.insertAlways(key, bslmf::MovableRefUtil::move(value));
844}
845
846template <class KEY, class VALUE, class HASH, class EQUAL>
847template <class RANDOM_ITER>
848inline
850 RANDOM_ITER first,
851 RANDOM_ITER last)
852{
853 BSLS_ASSERT(first <= last);
854
855 d_imp.insertBulkAlways(first, last);
856}
857
858template <class KEY, class VALUE, class HASH, class EQUAL>
859inline
861 bsl::size_t numBuckets)
862{
863 d_imp.rehash(numBuckets);
864}
865
866template <class KEY, class VALUE, class HASH, class EQUAL>
867inline
868int
870 const KEY& key,
871 const VisitorFunction& visitor)
872{
873 return d_imp.setComputedValueAll(key, visitor);
874}
875
876template <class KEY, class VALUE, class HASH, class EQUAL>
877inline
878int
880 const KEY& key,
881 const VisitorFunction& visitor)
882{
883 return d_imp.setComputedValueFirst(key, visitor);
884}
885
886template <class KEY, class VALUE, class HASH, class EQUAL>
887inline
889 const KEY& key,
890 const VALUE& value)
891{
892 return d_imp.setValueAll(key, value);
893}
894
895template <class KEY, class VALUE, class HASH, class EQUAL>
896inline
898 const KEY& key,
899 const VALUE& value)
900{
901 return d_imp.setValueFirst(key, value);
902}
903
904template <class KEY, class VALUE, class HASH, class EQUAL>
905inline
907 const KEY& key,
909{
910 return d_imp.setValueFirst(key, bslmf::MovableRefUtil::move(value));
911}
912
913template <class KEY, class VALUE, class HASH, class EQUAL>
914inline
916 const KEY& key,
917 const VisitorFunction& visitor)
918{
919 return d_imp.update(key, visitor);
920}
921
922template <class KEY, class VALUE, class HASH, class EQUAL>
923inline
925 const VisitorFunction& visitor)
926{
927 return d_imp.visit(visitor);
928}
929
930template <class KEY, class VALUE, class HASH, class EQUAL>
931inline
933 const KEY& key,
934 const VisitorFunction& visitor)
935{
936 return d_imp.visit(key, visitor);
937}
938
939// ACCESSORS
940template <class KEY, class VALUE, class HASH, class EQUAL>
941inline
942bsl::size_t
944{
945 return d_imp.bucketCount();
946}
947
948template <class KEY, class VALUE, class HASH, class EQUAL>
949inline
951 const KEY& key) const
952{
953 return d_imp.bucketIndex(key);
954}
955
956template <class KEY, class VALUE, class HASH, class EQUAL>
957inline
959 bsl::size_t index) const
960{
961 BSLS_ASSERT(bucketCount() > index);
962
963 return d_imp.bucketSize(index);
964}
965
966template <class KEY, class VALUE, class HASH, class EQUAL>
967inline
969{
970 return d_imp.empty();
971}
972
973template <class KEY, class VALUE, class HASH, class EQUAL>
974inline
976{
977 return d_imp.equalFunction();
978}
979
980template <class KEY, class VALUE, class HASH, class EQUAL>
981inline
983 bsl::vector<VALUE> *valuesPtr,
984 const KEY& key) const
985{
986 return d_imp.getValue(valuesPtr, key);
987}
988
989template <class KEY, class VALUE, class HASH, class EQUAL>
990inline
992 std::vector<VALUE> *valuesPtr,
993 const KEY& key) const
994{
995 return d_imp.getValue(valuesPtr, key);
996}
997
998#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
999template <class KEY, class VALUE, class HASH, class EQUAL>
1000inline
1002 std::pmr::vector<VALUE> *valuesPtr,
1003 const KEY& key) const
1004{
1005 return d_imp.getValue(valuesPtr, key);
1006}
1007#endif
1008
1009template <class KEY, class VALUE, class HASH, class EQUAL>
1010inline
1012 VALUE *value,
1013 const KEY& key) const
1014{
1015 return d_imp.getValue(value, key);
1016}
1017
1018template <class KEY, class VALUE, class HASH, class EQUAL>
1019inline
1021{
1022 return d_imp.hashFunction();
1023}
1024
1025template <class KEY, class VALUE, class HASH, class EQUAL>
1026inline
1028{
1029 return d_imp.isRehashEnabled();
1030}
1031
1032template <class KEY, class VALUE, class HASH, class EQUAL>
1033inline
1035{
1036 return d_imp.loadFactor();
1037}
1038
1039template <class KEY, class VALUE, class HASH, class EQUAL>
1040inline
1041float
1043{
1044 return d_imp.maxLoadFactor();
1045}
1046
1047template <class KEY, class VALUE, class HASH, class EQUAL>
1048inline
1050 const
1051{
1052 return d_imp.numStripes();
1053}
1054
1055template <class KEY, class VALUE, class HASH, class EQUAL>
1056inline
1058 const ReadOnlyVisitorFunction& visitor) const
1059{
1060 return d_imp.visitReadOnly(visitor);
1061}
1062
1063template <class KEY, class VALUE, class HASH, class EQUAL>
1064inline
1066 const KEY& key,
1067 const ReadOnlyVisitorFunction& visitor) const
1068{
1069 return d_imp.visitReadOnly(key, visitor);
1070}
1071
1072template <class KEY, class VALUE, class HASH, class EQUAL>
1073inline
1075{
1076 return d_imp.size();
1077}
1078
1079 // Aspects
1080
1081template <class KEY, class VALUE, class HASH, class EQUAL>
1082inline
1084 allocator() const
1085{
1086 return d_imp.allocator();
1087}
1088
1089} // close package namespace
1090
1091namespace bslma {
1092
1093template <class KEY, class VALUE, class HASH, class EQUAL>
1098
1099} // close namespace bslma
1100
1101
1102
1103#endif
1104
1105// ----------------------------------------------------------------------------
1106// Copyright 2018 Bloomberg Finance L.P.
1107//
1108// Licensed under the Apache License, Version 2.0 (the "License"); you may not
1109// use this file except in compliance with the License. You may obtain a copy
1110// of the License at
1111//
1112// http://www.apache.org/licenses/LICENSE-2.0
1113//
1114// Unless required by applicable law or agreed to in writing, software
1115// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1116// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1117// License for the specific language governing permissions and limitations
1118// under the License.
1119// ----------------------------- END-OF-FILE ----------------------------------
1120
1121/** @} */
1122/** @} */
1123/** @} */
Definition bdlcc_stripedunorderedcontainerimpl.h:542
Definition bdlcc_stripedunorderedmultimap.h:290
bsl::size_t setValueAll(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:888
int setComputedValueFirst(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:879
void insertBulk(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedmultimap.h:849
bsl::size_t setValueFirst(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:897
bool isRehashEnabled() const
Return true if rehash is enabled, or false otherwise.
Definition bdlcc_stripedunorderedmultimap.h:1027
void rehash(bsl::size_t numBuckets)
Definition bdlcc_stripedunorderedmultimap.h:860
void insert(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:830
bsl::size_t bucketCount() const
Definition bdlcc_stripedunorderedmultimap.h:943
bsl::size_t eraseAllIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedmultimap.h:791
@ k_DEFAULT_NUM_STRIPES
Definition bdlcc_stripedunorderedmultimap.h:314
@ k_DEFAULT_NUM_BUCKETS
Definition bdlcc_stripedunorderedmultimap.h:313
int visit(const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:924
int visitReadOnly(const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedmultimap.h:1057
HASH hashFunction() const
Definition bdlcc_stripedunorderedmultimap.h:1020
bsl::size_t bucketSize(bsl::size_t index) const
Definition bdlcc_stripedunorderedmultimap.h:958
bsl::size_t eraseFirst(const KEY &key)
Definition bdlcc_stripedunorderedmultimap.h:812
float loadFactor() const
Definition bdlcc_stripedunorderedmultimap.h:1034
bsl::size_t size() const
Return the current number of elements in this hash map.
Definition bdlcc_stripedunorderedmultimap.h:1074
bsl::function< bool(VALUE *, const KEY &)> VisitorFunction
Definition bdlcc_stripedunorderedmultimap.h:332
bsl::function< bool(const VALUE &, const KEY &)> ReadOnlyVisitorFunction
Definition bdlcc_stripedunorderedmultimap.h:346
int update(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:915
bsl::size_t eraseFirstIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedmultimap.h:821
float maxLoadFactor() const
Definition bdlcc_stripedunorderedmultimap.h:1042
bsl::size_t numStripes() const
Return the number of stripes in the hash.
Definition bdlcc_stripedunorderedmultimap.h:1049
EQUAL equalFunction() const
Definition bdlcc_stripedunorderedmultimap.h:975
bool empty() const
Definition bdlcc_stripedunorderedmultimap.h:968
void clear()
Definition bdlcc_stripedunorderedmultimap.h:762
bsl::size_t eraseAll(const KEY &key)
Definition bdlcc_stripedunorderedmultimap.h:783
bsl::size_t getValueFirst(VALUE *value, const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:1011
bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedmultimap.h:801
void enableRehash()
Definition bdlcc_stripedunorderedmultimap.h:776
bsl::function< bool(const VALUE &)> EraseIfValuePredicate
Definition bdlcc_stripedunorderedmultimap.h:356
bsl::size_t bucketIndex(const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:950
int setComputedValueAll(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:869
void disableRehash()
Prevent future rehash until enableRehash is called.
Definition bdlcc_stripedunorderedmultimap.h:769
bsl::pair< KEY, VALUE > KVType
Value type of a bulk insert entry.
Definition bdlcc_stripedunorderedmultimap.h:320
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedmultimap.h:1084
bsl::size_t getValueAll(bsl::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:982
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_pair.h:1280
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslmf_movableref.h:752
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlcc_boundedqueue.h:270
Definition baljsn_encoder_testtypes.h:76
Definition bslstl_equalto.h:316
Definition bslstl_hash.h:495
Definition bslma_usesbslmaallocator.h:344
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067