BDE 4.14.0 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 // NOT IMPLEMENTED
304 // = delete
307 // = delete
308
309 public:
310 // PUBLIC CONSTANTS
311 enum {
312 k_DEFAULT_NUM_BUCKETS = 16, // Default number of buckets
313 k_DEFAULT_NUM_STRIPES = 4 // Default number of stripes
314 };
315
316 // PUBLIC TYPES
317
318 /// Value type of a bulk insert entry.
320
321 /// An alias to a function meeting the following contract:
322 /// @code
323 /// /// Visit the specified `value` attribute associated with the
324 /// /// specified `key`. Return `true` if this function may be
325 /// /// called on additional elements, and `false` otherwise (i.e.,
326 /// /// if no other elements should be visited). Note that this
327 /// /// functor can change the value associated with `key`.
328 /// bool visitorFunction(VALUE *value, const KEY& key);
329 /// @endcode
330 typedef bsl::function<bool (VALUE *, const KEY&)> VisitorFunction;
331
332 /// An alias to a function meeting the following contract:
333 /// @code
334 /// /// Visit the specified `value` attribute associated with the
335 /// /// specified `key`. Return `true` if this function may be
336 /// /// called on additional elements, and `false` otherwise (i.e.,
337 /// /// if no other elements should be visited). Note that this
338 /// /// functor can *not* change the values associated with `key`
339 /// /// and `value`.
340 /// bool readOnlyVisitorFunction(const VALUE& value, const KEY& key);
341 /// @endcode
342 typedef bsl::function<bool (const VALUE&, const KEY&)>
344
345 /// An alias to a function meeting the following contract:
346 /// @code
347 /// /// Return `true` if the specified `value` is to be removed from
348 /// /// the container, and `false` otherwise. Note that this
349 /// /// functor can *not* change the values associated with `value`.
350 /// bool eraseIfValuePredicate(const VALUE& value);
351 /// @endcode
352 typedef bsl::function<bool(const VALUE&)> EraseIfValuePredicate;
353
354 // CREATORS
355
357 bsl::size_t numInitialBuckets = k_DEFAULT_NUM_BUCKETS,
358 bsl::size_t numStripes = k_DEFAULT_NUM_STRIPES,
359 bslma::Allocator *basicAllocator = 0);
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
367 /// is used. The hash map has rehash enabled. Note that the number of
368 /// stripes will not change after construction, but the number of
369 /// buckets may (unless rehashing is disabled via `disableRehash`).
371 bslma::Allocator *basicAllocator);
372
374 // Destroy this hash map.
375
376 // MANIPULATORS
377
378 /// Remove all elements from this hash map. If rehash is in progress,
379 /// block until it completes.
380 void clear();
381
382 /// Prevent future rehash until `enableRehash` is called.
383 void disableRehash();
384
385 /// Allow rehash. If conditions warrant, rehash will be started by the
386 /// *next* method call that observes the load factor is exceeded (see
387 /// {Concurrent Rehash}). Note that calling
388 /// `maxLoadFactor(maxLoadFactor())` (i.e., setting the maximum load
389 /// factor to its current value) will trigger a rehash if needed but
390 /// otherwise does not change the hash map.
391 void enableRehash();
392
393 /// Erase from this hash map the elements having the specified `key`.
394 /// Return the number of elements erased.
395 bsl::size_t eraseAll(const KEY& key);
396
397 /// Erase from this hash map the elements having the specified `key` for
398 /// which the specified `predicate` holds true. Return the number of
399 /// elements erased.
400 bsl::size_t eraseAllIf(const KEY& key,
401 const EraseIfValuePredicate& predicate);
402
403 /// Erase from this hash map elements in this hash map having any of the
404 /// values in the keys contained between the specified `first`
405 /// (inclusive) and `last` (exclusive) random-access iterators. The
406 /// iterators provide read access to a sequence of `KEY` objects. All
407 /// erasures are done by the calling thread and the order of erasure is
408 /// not specified. Return the number of elements removed. The behavior
409 /// is undefined unless `first <= last`. Note that the map may not have
410 /// an element for every value in `keys`.
411 template <class RANDOM_ITER>
412 bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last);
413
414 /// Erase from this hash map the *first* element (of possibly many)
415 /// found to the specified `key`. Return the number of elements erased.
416 /// Note that method is more performant than `eraseAll` when there is
417 /// one element having `key`.
418 bsl::size_t eraseFirst(const KEY& key);
419
420 /// Erase from this hash map the *first* element (of possibly many) with
421 /// specified `key` found, for which the specified `predicate` holds
422 /// true. Return the number of elements erased.
423 bsl::size_t eraseFirstIf(const KEY& key,
424 const EraseIfValuePredicate& predicate);
425
426 /// Insert into this hash map an element having the specified `key` and
427 /// `value`. Note that other elements having the same `key` may exist
428 /// in this hash map.
429 void insert(const KEY& key, const VALUE& value);
430
431 /// Insert into this hash map an element having the specified `key` and
432 /// the specified move-insertable `value`. The `value` object is left
433 /// in a valid but unspecified state. If `value` is allocator-enabled
434 /// and `allocator() != value.allocator()` this operation may cost as
435 /// much as a copy. Note that other elements having the same `key` may
436 /// exist in this hash map.
437 void insert(const KEY& key, bslmf::MovableRef<VALUE> value);
438
439 /// Insert into this hash map elements having the key-value pairs
440 /// obtained between the specified `first` (inclusive) and `last`
441 /// (exclusive) random-access iterators. The iterators provide read
442 /// access to a sequence of `bsl::pair<KEY, VALUE>` objects. All
443 /// insertions are done by the calling thread and the order of insertion
444 /// is not specified. The behavior is undefined unless `first <= last`.
445 template <class RANDOM_ITER>
446 void insertBulk(RANDOM_ITER first, RANDOM_ITER last);
447
448 /// Set the maximum load factor of this unordered map to the specified
449 /// `newMaxLoadFactor`. If `newMaxLoadFactor < loadFactor()`, this
450 /// operation will cause an immediate rehash; otherwise, this operation
451 /// has a constant-time cost. The rehash will increase the number of
452 /// buckets by a power of 2. The behavior is undefined unless
453 /// `0 < newMaxLoadFactor`.
454 void maxLoadFactor(float newMaxLoadFactor);
455
456 /// Recreate this hash map to one having at least the specified
457 /// `numBuckets`. This operation is a no-op if *any* of the following
458 /// are true: 1) rehash is disabled; 2) `numBuckets` less or equals the
459 /// current number of buckets. See {Rehash}.
460 void rehash(bsl::size_t numBuckets);
461
462 /// Serially invoke the specified `visitor` passing the specified `key`,
463 /// and the address of the value of each element in this hash map having
464 /// `key`. If `key` is not in the map, `value` will be default
465 /// constructed. That is, for each `(key, value)` found, invoke:
466 /// @code
467 /// bool visitor(VALUE *value, const Key& key);
468 /// @endcode
469 /// If no element in the map has `key`, insert `(key, VALUE())` and
470 /// invoke `visitor` with `value` pointing to the default constructed
471 /// value. Return the number of elements visited or the negation of
472 /// that value if visitations stopped because `visitor` returned
473 /// `false`. `visitor`, when invoked, has exclusive access (i.e., write
474 /// access) to each element during each invocation. The behavior is
475 /// undefined if hash map manipulators and `getValue*` methods are
476 /// invoked from within `visitor`, as it may lead to a deadlock. Note
477 /// that the `setComputedValueFirst` method is more performant than the
478 /// when the hash map contains a single element for `key`. Also note
479 /// that a return value of `0` implies that an element was inserted.
480 int setComputedValueAll(const KEY& key,
481 const VisitorFunction& visitor);
482
483 /// Invoke the specified `visitor` passing the specified `key`, and the
484 /// address of the value attribute of the *first* element (of possibly
485 /// many elements) found in this hash map having `key`. If `key` is not
486 /// in the map, `value` will be default constructed. That is, for
487 /// `(key, value)`, invoke:
488 /// @code
489 /// bool visitor(VALUE *value, const Key& key);
490 /// @endcode
491 /// If no element in the map has `key`, insert `(key, VALUE())` and
492 /// invoke `visitor` with `value` pointing to the default constructed
493 /// value. Return 1 if `key` was found and `visitor` returned `true`, 0
494 /// if `key` was not found, and -1 if `key` was found and `visitor`
495 /// returned `false`. `visitor`, when invoked, has exclusive access
496 /// (i.e., write access) to the element. The behavior is undefined if
497 /// hash map manipulators and `getValue*` methods are invoked from
498 /// within `visitor`, as it may lead to a deadlock. Note that the
499 /// return value equals the number of elements inserted. Also note
500 /// that, when there are multiple elements having `key`, the selection
501 /// of "first" is implementation specific and subject to change. Also
502 /// note that this method is more performant than the
503 /// `setComputedValueAll` method when the hash map contains a single
504 /// element for `key`. Also note that a return value of `0` implies
505 /// that an element was inserted.
506 int setComputedValueFirst(const KEY& key,
507 const VisitorFunction& visitor);
508
509 /// Set the value attribute of every element in this hash map having the
510 /// specified `key` to the specified `value`. If no such such element
511 /// exists, insert `(key, value)`. Return the number of elements found
512 /// with `key`. Note that if no elements were found, and a new value
513 /// was inserted, `0` is returned.
514 bsl::size_t setValueAll(const KEY& key, const VALUE& value);
515
516 /// Set the value attribute of the *first* element in this hash map (of
517 /// possibly many) found to have the specified `key` to the specified
518 /// `value`. If no such such element exists, insert `(key, value)`.
519 /// Return the number of elements found with `key`. Note that if no
520 /// elements were found, and a new value was inserted, `0` is returned.
521 /// Also note that this method is more performant than `setValueAll`
522 /// when there is one element having `key` in the hash map.
523 bsl::size_t setValueFirst(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 /// move-insertable `value`. If no such such element exists, insert
528 /// `(key, value)`. Return the number of elements found with `key`.
529 /// The `value` object is left in a valid but unspecified state. If
530 /// `value` is allocator-enabled and `allocator() != value.allocator()`
531 /// this operation may cost as much as a copy. Note that if no elements
532 /// were found, and a new value was inserted, `0` is returned. Also
533 /// note that this method is more performant than `setValueAll` when
534 /// there is one element having `key` in the hash map.
535 bsl::size_t setValueFirst(const KEY& key, bslmf::MovableRef<VALUE> value);
536
537 /// @deprecated Use @ref visit(key, visitor) instead.
538 ///
539 /// Serially call the specified `visitor` on each element (if one
540 /// exists) in this hash map having the specified `key` until every such
541 /// element has been updated or `visitor` returns `false`. That is, for
542 /// `(key, value)`, invoke:
543 /// @code
544 /// bool visitor(&value, key);
545 /// @endcode
546 /// Return the number of elements visited or the negation of that value
547 /// if visitations stopped because `visitor` returned `false`.
548 /// `visitor` has exclusive access (i.e., write access) to each element
549 /// for duration of each invocation. The behavior is undefined if hash
550 /// map manipulators and `getValue*` methods are invoked from within
551 /// `visitor`, as it may lead to a deadlock.
552 int update(const KEY& key, const VisitorFunction& visitor);
553
554 /// Call the specified `visitor` (in an unspecified order) on the
555 /// elements in this hash table until each such element has been visited
556 /// or `visitor` returns `false`. That is, for `(key, value)`, invoke:
557 /// @code
558 /// bool visitor(&value, key);
559 /// @endcode
560 /// Return the number of elements visited or the negation of that value
561 /// if visitations stopped because `visitor` returned `false`.
562 /// `visitor` has exclusive access (i.e., write access) to each element
563 /// for duration of each invocation. Every element present in this hash
564 /// map at the time `visit` is invoked will be visited unless it is
565 /// removed before `visitor` is called for that element. Each
566 /// visitation is done by the calling thread and the order of visitation
567 /// is not specified. Elements inserted during the execution of `visit`
568 /// may or may not be visited. The behavior is undefined if hash map
569 /// manipulators and `getValue*` methods are invoked from within
570 /// `visitor`, as it may lead to a deadlock. Note that `visitor` can
571 /// change the value of the visited elements.
572 int visit(const VisitorFunction& visitor);
573
574 /// Serially call the specified `visitor` on each element (if one
575 /// exists) in this hash map having the specified `key` until every such
576 /// element has been updated or `visitor` returns `false`. That is, for
577 /// `(key, value)`, invoke:
578 /// @code
579 /// bool visitor(&value, key);
580 /// @endcode
581 /// Return the number of elements visited or the negation of that value
582 /// if visitations stopped because `visitor` returned `false`.
583 /// `visitor` has exclusive access (i.e., write access) to each element
584 /// for duration of each invocation. The behavior is undefined if hash
585 /// map manipulators and `getValue*` methods are invoked from within
586 /// `visitor`, as it may lead to a deadlock.
587 int visit(const KEY& key, const VisitorFunction& visitor);
588
589 // ACCESSORS
590
591 /// Return the number of buckets in the array of buckets maintained by
592 /// this hash map. Note that unless rehash is disabled, the value
593 /// returned may be obsolete by the time it is received.
594 bsl::size_t bucketCount() const;
595
596 /// Return the index of the bucket, in the array of buckets maintained
597 /// by this hash map, where elements having the specified `key` are
598 /// inserted. Note that unless rehash is disabled, the value returned
599 /// may be obsolete at the time it is returned.
600 bsl::size_t bucketIndex(const KEY& key) const;
601
602 /// Return the number of elements contained in the bucket at the
603 /// specified `index` in the array of buckets maintained by this hash
604 /// map. The behavior is undefined unless
605 /// `0 <= index < bucketCount()`. Note that unless rehash is disabled
606 /// the value returned may be obsolete by the time it is returned.
607 bsl::size_t bucketSize(bsl::size_t index) const;
608
609 /// Return `true` if this hash map contains no elements, and `false`
610 /// otherwise.
611 bool empty() const;
612
613 /// Return (a copy of) the key-equality functor used by this hash map.
614 /// The returned function will return `true` if two `KEY` objects have
615 /// the same value, and `false` otherwise.
616 EQUAL equalFunction() const;
617
618 bsl::size_t getValueAll(bsl::vector<VALUE> *valuesPtr,
619 const KEY& key) const;
620 bsl::size_t getValueAll(std::vector<VALUE> *valuesPtr,
621 const KEY& key) const;
622#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
623 /// Load, into the specified `*valuesPtr`, the value attributes of every
624 /// element in this hash map having the specified `key`. Return the
625 /// number of elements found with `key`. Note that the order of the
626 /// values returned is not specified.
627 bsl::size_t getValueAll(std::pmr::vector<VALUE> *valuesPtr,
628 const KEY& key) const;
629#endif
630
631 /// Load, into the specified `*value`, the value attribute of the first
632 /// element found in this hash map having the specified `key`. Return 1
633 /// on success, and 0 if `key` does not exist in this hash map. Note
634 /// that the return value equals the number of values returned.
635 bsl::size_t getValueFirst(VALUE *value, const KEY& key) const;
636
637 /// Return (a copy of) the unary hash functor used by this hash map.
638 /// The return function will generate a hash value (of type
639 /// `std::size_t`) for a `KEY` object.
640 HASH hashFunction() const;
641
642 /// Return `true` if rehash is enabled, or `false` otherwise.
643 bool isRehashEnabled() const;
644
645 /// Return the current quotient of the size of this hash map and the
646 /// number of buckets. Note that the load factor is a measure of
647 /// container "fullness"; that is, a high load factor typically implies
648 /// many collisions (many elements landing in the same bucket) and that
649 /// decreases performance. See {Rehash Control}.
650 float loadFactor() const;
651
652 /// Return the maximum load factor allowed for this hash map. If an
653 /// insert operation would cause the load factor to exceed the
654 /// `maxLoadFactor()` and rehashing is enabled, then that insert
655 /// increases the number of buckets and rehashes the elements of the
656 /// container into that larger set of buckets. See {Rehash Control}.
657 float maxLoadFactor() const;
658
659 /// Return the number of stripes in the hash.
660 bsl::size_t numStripes() const;
661
662 /// Call the specified `visitor` (in an unspecified order) on the
663 /// elements in this hash table until each such element has been visited
664 /// or `visitor` returns `false`. That is, for `(key, value)`, invoke:
665 /// @code
666 /// bool visitor(value, key);
667 /// @endcode
668 /// Return the number of elements visited or the negation of that value
669 /// if visitations stopped because `visitor` returned `false`.
670 /// `visitor` has read-only access to each element for duration of each
671 /// invocation. Every element present in this hash map at the time
672 /// `visit` is invoked will be visited unless it is removed before
673 /// `visitor` is called for that element. Each visitation is done by
674 /// the calling thread and the order of visitation is not specified. The
675 /// behavior is undefined if hash map manipulators are invoked from
676 /// within `visitor`, as it may lead to a deadlock. Note that `visitor`
677 /// can *not* change the value of the visited elements.
678 int visitReadOnly(const ReadOnlyVisitorFunction& visitor) const;
679
680 /// Serially call the specified `visitor` on each element (if one
681 /// exists) in this hash map having the specified `key` until every such
682 /// element has been visited or `visitor` returns `false`. That is, for
683 /// `(key, value)`, invoke:
684 /// @code
685 /// bool visitor(value, key);
686 /// @endcode
687 /// Return the number of elements visited or the negation of that value
688 /// if visitations stopped because `visitor` returned `false`.
689 /// `visitor` has read-only access to each element for duration of each
690 /// invocation. The behavior is undefined if hash map manipulators are
691 /// invoked from within `visitor`, as it may lead to a deadlock.
692 int visitReadOnly(const KEY& key,
693 const ReadOnlyVisitorFunction& visitor) const;
694
695 /// Return the current number of elements in this hash map.
696 bsl::size_t size() const;
697
698 // Aspects
699
700 /// Return the allocator used by this hash map to supply memory. Note
701 /// that if no allocator was supplied at construction the default
702 /// allocator installed at that time is used.
704};
705
706// ============================================================================
707// INLINE DEFINITIONS
708// ============================================================================
709
710 // ------------------------------
711 // class StripedUnorderedMultiMap
712 // ------------------------------
713
714// CREATORS
715template <class KEY, class VALUE, class HASH, class EQUAL>
716inline
718 bsl::size_t numInitialBuckets,
719 bsl::size_t numStripes,
720 bslma::Allocator *basicAllocator)
721: d_imp(numInitialBuckets, numStripes, basicAllocator)
722{
723}
724
725template <class KEY, class VALUE, class HASH, class EQUAL>
726inline
728 bslma::Allocator *basicAllocator)
729: d_imp(k_DEFAULT_NUM_BUCKETS, k_DEFAULT_NUM_STRIPES, basicAllocator)
730{
731}
732
733// MANIPULATORS
734template <class KEY, class VALUE, class HASH, class EQUAL>
735inline
740
741template <class KEY, class VALUE, class HASH, class EQUAL>
742inline
747
748template <class KEY, class VALUE, class HASH, class EQUAL>
749inline
754
755template <class KEY, class VALUE, class HASH, class EQUAL>
756inline
758 const KEY& key)
759{
760 return d_imp.eraseAll(key);
761}
762
763template <class KEY, class VALUE, class HASH, class EQUAL>
764inline
766 const KEY& key,
767 const EraseIfValuePredicate& predicate)
768{
769 return d_imp.eraseAllIf(key, predicate);
770}
771
772template <class KEY, class VALUE, class HASH, class EQUAL>
773template <class RANDOM_ITER>
774inline
776 RANDOM_ITER first,
777 RANDOM_ITER last)
778{
779 BSLS_ASSERT(first <= last);
780
781 return d_imp.eraseBulkAll(first, last);
782}
783
784template <class KEY, class VALUE, class HASH, class EQUAL>
785inline
787 const KEY& key)
788{
789 return d_imp.eraseFirst(key);
790}
791
792template <class KEY, class VALUE, class HASH, class EQUAL>
793inline
794bsl::size_t
796 const KEY& key,
797 const EraseIfValuePredicate& predicate)
798{
799 return d_imp.eraseFirstIf(key, predicate);
800}
801
802template <class KEY, class VALUE, class HASH, class EQUAL>
803inline
805 const KEY& key,
806 const VALUE& value)
807{
808 d_imp.insertAlways(key, value);
809}
810
811template <class KEY, class VALUE, class HASH, class EQUAL>
812inline
814 const KEY& key,
816{
817 d_imp.insertAlways(key, bslmf::MovableRefUtil::move(value));
818}
819
820template <class KEY, class VALUE, class HASH, class EQUAL>
821template <class RANDOM_ITER>
822inline
824 RANDOM_ITER first,
825 RANDOM_ITER last)
826{
827 BSLS_ASSERT(first <= last);
828
829 d_imp.insertBulkAlways(first, last);
830}
831
832template <class KEY, class VALUE, class HASH, class EQUAL>
833inline
835 float newMaxLoadFactor)
836{
837 BSLS_ASSERT(0 < newMaxLoadFactor);
838
839 d_imp.maxLoadFactor(newMaxLoadFactor);
840}
841
842template <class KEY, class VALUE, class HASH, class EQUAL>
843inline
845 bsl::size_t numBuckets)
846{
847 d_imp.rehash(numBuckets);
848}
849
850template <class KEY, class VALUE, class HASH, class EQUAL>
851inline
852int
854 const KEY& key,
855 const VisitorFunction& visitor)
856{
857 return d_imp.setComputedValueAll(key, visitor);
858}
859
860template <class KEY, class VALUE, class HASH, class EQUAL>
861inline
862int
864 const KEY& key,
865 const VisitorFunction& visitor)
866{
867 return d_imp.setComputedValueFirst(key, visitor);
868}
869
870template <class KEY, class VALUE, class HASH, class EQUAL>
871inline
873 const KEY& key,
874 const VALUE& value)
875{
876 return d_imp.setValueAll(key, value);
877}
878
879template <class KEY, class VALUE, class HASH, class EQUAL>
880inline
882 const KEY& key,
883 const VALUE& value)
884{
885 return d_imp.setValueFirst(key, value);
886}
887
888template <class KEY, class VALUE, class HASH, class EQUAL>
889inline
891 const KEY& key,
893{
894 return d_imp.setValueFirst(key, bslmf::MovableRefUtil::move(value));
895}
896
897template <class KEY, class VALUE, class HASH, class EQUAL>
898inline
900 const KEY& key,
901 const VisitorFunction& visitor)
902{
903 return d_imp.update(key, visitor);
904}
905
906template <class KEY, class VALUE, class HASH, class EQUAL>
907inline
909 const VisitorFunction& visitor)
910{
911 return d_imp.visit(visitor);
912}
913
914template <class KEY, class VALUE, class HASH, class EQUAL>
915inline
917 const KEY& key,
918 const VisitorFunction& visitor)
919{
920 return d_imp.visit(key, visitor);
921}
922
923// ACCESSORS
924template <class KEY, class VALUE, class HASH, class EQUAL>
925inline
926bsl::size_t
928{
929 return d_imp.bucketCount();
930}
931
932template <class KEY, class VALUE, class HASH, class EQUAL>
933inline
935 const KEY& key) const
936{
937 return d_imp.bucketIndex(key);
938}
939
940template <class KEY, class VALUE, class HASH, class EQUAL>
941inline
943 bsl::size_t index) const
944{
945 BSLS_ASSERT(bucketCount() > index);
946
947 return d_imp.bucketSize(index);
948}
949
950template <class KEY, class VALUE, class HASH, class EQUAL>
951inline
953{
954 return d_imp.empty();
955}
956
957template <class KEY, class VALUE, class HASH, class EQUAL>
958inline
960{
961 return d_imp.equalFunction();
962}
963
964template <class KEY, class VALUE, class HASH, class EQUAL>
965inline
967 bsl::vector<VALUE> *valuesPtr,
968 const KEY& key) const
969{
970 return d_imp.getValue(valuesPtr, key);
971}
972
973template <class KEY, class VALUE, class HASH, class EQUAL>
974inline
976 std::vector<VALUE> *valuesPtr,
977 const KEY& key) const
978{
979 return d_imp.getValue(valuesPtr, key);
980}
981
982#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
983template <class KEY, class VALUE, class HASH, class EQUAL>
984inline
986 std::pmr::vector<VALUE> *valuesPtr,
987 const KEY& key) const
988{
989 return d_imp.getValue(valuesPtr, key);
990}
991#endif
992
993template <class KEY, class VALUE, class HASH, class EQUAL>
994inline
996 VALUE *value,
997 const KEY& key) const
998{
999 return d_imp.getValue(value, key);
1000}
1001
1002template <class KEY, class VALUE, class HASH, class EQUAL>
1003inline
1005{
1006 return d_imp.hashFunction();
1007}
1008
1009template <class KEY, class VALUE, class HASH, class EQUAL>
1010inline
1012{
1013 return d_imp.isRehashEnabled();
1014}
1015
1016template <class KEY, class VALUE, class HASH, class EQUAL>
1017inline
1019{
1020 return d_imp.loadFactor();
1021}
1022
1023template <class KEY, class VALUE, class HASH, class EQUAL>
1024inline
1025float
1027{
1028 return d_imp.maxLoadFactor();
1029}
1030
1031template <class KEY, class VALUE, class HASH, class EQUAL>
1032inline
1034 const
1035{
1036 return d_imp.numStripes();
1037}
1038
1039template <class KEY, class VALUE, class HASH, class EQUAL>
1040inline
1042 const ReadOnlyVisitorFunction& visitor) const
1043{
1044 return d_imp.visitReadOnly(visitor);
1045}
1046
1047template <class KEY, class VALUE, class HASH, class EQUAL>
1048inline
1050 const KEY& key,
1051 const ReadOnlyVisitorFunction& visitor) const
1052{
1053 return d_imp.visitReadOnly(key, visitor);
1054}
1055
1056template <class KEY, class VALUE, class HASH, class EQUAL>
1057inline
1059{
1060 return d_imp.size();
1061}
1062
1063 // Aspects
1064
1065template <class KEY, class VALUE, class HASH, class EQUAL>
1066inline
1068 allocator() const
1069{
1070 return d_imp.allocator();
1071}
1072
1073} // close package namespace
1074
1075namespace bslma {
1076
1077template <class KEY, class VALUE, class HASH, class EQUAL>
1082
1083} // close namespace bslma
1084
1085
1086
1087#endif
1088
1089// ----------------------------------------------------------------------------
1090// Copyright 2018 Bloomberg Finance L.P.
1091//
1092// Licensed under the Apache License, Version 2.0 (the "License"); you may not
1093// use this file except in compliance with the License. You may obtain a copy
1094// of the License at
1095//
1096// http://www.apache.org/licenses/LICENSE-2.0
1097//
1098// Unless required by applicable law or agreed to in writing, software
1099// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1100// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1101// License for the specific language governing permissions and limitations
1102// under the License.
1103// ----------------------------- END-OF-FILE ----------------------------------
1104
1105/** @} */
1106/** @} */
1107/** @} */
Definition bdlcc_stripedunorderedcontainerimpl.h:473
Definition bdlcc_stripedunorderedmultimap.h:290
bsl::size_t setValueAll(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:872
int setComputedValueFirst(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:863
void insertBulk(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedmultimap.h:823
bsl::size_t setValueFirst(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:881
bool isRehashEnabled() const
Return true if rehash is enabled, or false otherwise.
Definition bdlcc_stripedunorderedmultimap.h:1011
void rehash(bsl::size_t numBuckets)
Definition bdlcc_stripedunorderedmultimap.h:844
void insert(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedmultimap.h:804
bsl::size_t bucketCount() const
Definition bdlcc_stripedunorderedmultimap.h:927
bsl::size_t eraseAllIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedmultimap.h:765
@ k_DEFAULT_NUM_STRIPES
Definition bdlcc_stripedunorderedmultimap.h:313
@ k_DEFAULT_NUM_BUCKETS
Definition bdlcc_stripedunorderedmultimap.h:312
int visit(const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:908
int visitReadOnly(const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedmultimap.h:1041
HASH hashFunction() const
Definition bdlcc_stripedunorderedmultimap.h:1004
bsl::size_t bucketSize(bsl::size_t index) const
Definition bdlcc_stripedunorderedmultimap.h:942
bsl::size_t eraseFirst(const KEY &key)
Definition bdlcc_stripedunorderedmultimap.h:786
float loadFactor() const
Definition bdlcc_stripedunorderedmultimap.h:1018
bsl::size_t size() const
Return the current number of elements in this hash map.
Definition bdlcc_stripedunorderedmultimap.h:1058
bsl::function< bool(VALUE *, const KEY &)> VisitorFunction
Definition bdlcc_stripedunorderedmultimap.h:330
bsl::function< bool(const VALUE &, const KEY &)> ReadOnlyVisitorFunction
Definition bdlcc_stripedunorderedmultimap.h:343
int update(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:899
bsl::size_t eraseFirstIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedmultimap.h:795
float maxLoadFactor() const
Definition bdlcc_stripedunorderedmultimap.h:1026
bsl::size_t numStripes() const
Return the number of stripes in the hash.
Definition bdlcc_stripedunorderedmultimap.h:1033
EQUAL equalFunction() const
Definition bdlcc_stripedunorderedmultimap.h:959
bool empty() const
Definition bdlcc_stripedunorderedmultimap.h:952
void clear()
Definition bdlcc_stripedunorderedmultimap.h:736
bsl::size_t eraseAll(const KEY &key)
Definition bdlcc_stripedunorderedmultimap.h:757
bsl::size_t getValueFirst(VALUE *value, const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:995
bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedmultimap.h:775
void enableRehash()
Definition bdlcc_stripedunorderedmultimap.h:750
bsl::function< bool(const VALUE &)> EraseIfValuePredicate
Definition bdlcc_stripedunorderedmultimap.h:352
bsl::size_t bucketIndex(const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:934
int setComputedValueAll(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedmultimap.h:853
void disableRehash()
Prevent future rehash until enableRehash is called.
Definition bdlcc_stripedunorderedmultimap.h:743
bsl::pair< KEY, VALUE > KVType
Value type of a bulk insert entry.
Definition bdlcc_stripedunorderedmultimap.h:319
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedmultimap.h:1068
bsl::size_t getValueAll(bsl::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedmultimap.h:966
Forward declaration.
Definition bslstl_function.h:934
Definition bslstl_pair.h:1210
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
Definition bslmf_movableref.h:751
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlcc_boundedqueue.h:270
Definition balxml_encoderoptions.h:68
Definition bslstl_equalto.h:311
Definition bslstl_hash.h:498
Definition bslma_usesbslmaallocator.h:343
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060