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