8#ifndef INCLUDED_BDLCC_STRIPEDUNORDEREDCONTAINERIMPL
9#define INCLUDED_BDLCC_STRIPEDUNORDEREDCONTAINERIMPL
148#include <bdlscm_version.h>
179#include <bsl_algorithm.h>
180#include <bsl_cstddef.h>
181#include <bsl_functional.h>
182#include <bsl_iostream.h>
183#include <bsl_limits.h>
185#include <bsl_optional.h>
186#include <bsl_sstream.h>
187#include <bsl_vector.h>
198class StripedUnorderedContainerImpl;
227 const bool d_lockSucceeded;
265template <
class KEY,
class VALUE>
340 const KEY&
key()
const;
346 const VALUE&
value()
const;
364template <
class KEY,
class VALUE>
372 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
450 void setSize(bsl::size_t value);
475 template <
class EQUAL>
476 bsl::size_t
setValue(
const KEY& key,
491 template <
class EQUAL>
492 bsl::size_t
setValue(
const KEY& key,
506 bsl::size_t
size()
const;
541template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
596 #if BSLS_PLATFORM_CPU_X86 || BSLS_PLATFORM_CPU_X86_64
597 k_PREFETCH_ENABLED = 1,
599 k_PREFETCH_ENABLED = 0,
602 k_EFFECTIVE_CACHELINE_SIZE = (1 + k_PREFETCH_ENABLED) *
630 typedef StripedUnorderedContainerImpl_LockElementReadGuard LERGuard;
631 typedef StripedUnorderedContainerImpl_LockElementWriteGuard LEWGuard;
633#ifdef BSLS_PLATFORM_CPU_32_BIT
638 BSLMF_ASSERT(
sizeof(AtomicSizeT) ==
sizeof(bsl::size_t));
639 BSLMF_ASSERT(!bsl::numeric_limits<bsl::size_t>::is_signed);
644 const bsl::size_t d_numStripes;
647 AtomicSizeT d_numBuckets;
652 const bsl::size_t d_hashMask;
655 const float d_maxLoadFactor;
668 const char d_statePad[k_INT_PADDING];
674 const char d_numElementsPad[k_INT_PADDING];
682 LockElement *d_locks_p;
707 static bsl::size_t adjustBuckets(bsl::size_t numBuckets,
711 static bool alwaysTrue(
const VALUE&);
714 static bsl::size_t powerCeil(bsl::size_t num);
729 bsl::size_t erase(
const KEY& key, Scope scope);
743 template <
class RANDOM_ITER>
744 bsl::size_t eraseBulk(RANDOM_ITER first,
757 bsl::size_t eraseIf(
const KEY& key,
778 bsl::size_t insert(
const KEY& key,
780 Multiplicity multiplicity);
781 bsl::size_t insert(
const KEY& key,
783 Multiplicity multiplicity);
808 template <
class RANDOM_ITER>
809 bsl::size_t insertBulk(RANDOM_ITER first,
811 Multiplicity multiplicity);
836 int setComputedValue(
const KEY& key,
859 bsl::size_t setValue(
const KEY& key,
872 bsl::size_t bucketIndex(
const KEY& key, bsl::size_t numBuckets)
const;
875 bsl::size_t bucketToStripe(bsl::size_t bucketIndex)
const;
882 template <
class VECTOR>
883 bsl::size_t getValueImpl(VECTOR *valuesPtr,
const KEY& key)
const;
889 LockElement *lockRead(bsl::size_t *bucketIdx,
const KEY& key)
const;
895 LockElement *lockWrite(bsl::size_t *bucketIdx,
const KEY& key)
const;
972 template <
class RANDOM_ITER>
986 template <
class RANDOM_ITER>
1024 template <
class RANDOM_ITER>
1037 template <
class RANDOM_ITER>
1246 bsl::size_t
getValue(VALUE *value,
const KEY& key)
const;
1249 bsl::size_t
getValue(std::vector<VALUE> *valuesPtr,
const KEY& key)
const;
1250#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1251 bsl::size_t
getValue(std::pmr::vector<VALUE> *valuesPtr,
const KEY& key)
1341template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1398 #if BSLS_PLATFORM_CPU_X86 || BSLS_PLATFORM_CPU_X86_64
1399 k_PREFETCH_ENABLED = 1,
1401 k_PREFETCH_ENABLED = 0,
1404 k_EFFECTIVE_CACHELINE_SIZE = (1 + k_PREFETCH_ENABLED) *
1407 k_LOCK_PADDING = k_EFFECTIVE_CACHELINE_SIZE >=
sizeof(
LockType) ?
1408 k_EFFECTIVE_CACHELINE_SIZE -
sizeof(
LockType) :
1409 2 * k_EFFECTIVE_CACHELINE_SIZE -
sizeof(
LockType)
1414 const char d_pad[k_LOCK_PADDING];
1525 unsigned d_numLocked;
1585, d_lockSucceeded(trySetRehashBit(d_state_p))
1593 const int k_REHASH_IN_PROGRESS =
1595 const int k_REHASH_ENABLED =
1598 if (d_lockSucceeded) {
1599 int expected = k_REHASH_ENABLED | k_REHASH_IN_PROGRESS;
1603 expected & ~k_REHASH_IN_PROGRESS);
1604 if (previous == expected) {
1607 expected = previous;
1615 return d_lockSucceeded;
1619bool StripedUnorderedContainerImpl_RehashBitSetGuard::trySetRehashBit(
1622 const int k_REHASH_IN_PROGRESS =
1624 const int k_REHASH_ENABLED =
1628 return k_REHASH_ENABLED ==
1630 k_REHASH_ENABLED | k_REHASH_IN_PROGRESS);
1638template <
class KEY,
class VALUE>
1647, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1660template <
class KEY,
class VALUE>
1669, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1676 VALUE& dummy =
value;
1683template <
class KEY,
class VALUE>
1690, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1702template <
class KEY,
class VALUE>
1708 bslma::DestructionUtil::destroy(d_key.address());
1709 bslma::DestructionUtil::destroy(d_value.address());
1714template <
class KEY,
class VALUE>
1722template <
class KEY,
class VALUE>
1730template <
class KEY,
class VALUE>
1734 return d_value.object();
1738template <
class KEY,
class VALUE>
1742 return d_key.object();
1745template <
class KEY,
class VALUE>
1753template <
class KEY,
class VALUE>
1757 return d_value.object();
1762template <
class KEY,
class VALUE>
1767 return d_allocator_p;
1775template <
class KEY,
class VALUE>
1783, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1787template <
class KEY,
class VALUE>
1794: d_head_p(MoveUtil::move(MoveUtil::access(original).d_head_p))
1795, d_tail_p(MoveUtil::move(MoveUtil::access(original).d_tail_p))
1796, d_size( MoveUtil::access(original).d_size)
1797, d_allocator_p(MoveUtil::access(original).d_allocator_p)
1799 MoveUtil::access(original).d_head_p = NULL;
1800 MoveUtil::access(original).d_tail_p = NULL;
1801 MoveUtil::access(original).d_size = 0;
1804template <
class KEY,
class VALUE>
1813template <
class KEY,
class VALUE>
1820 if (d_head_p == NULL) {
1830template <
class KEY,
class VALUE>
1839 d_allocator_p->deleteObject(curNode);
1847template <
class KEY,
class VALUE>
1855template <
class KEY,
class VALUE>
1863template <
class KEY,
class VALUE>
1871template <
class KEY,
class VALUE>
1879template <
class KEY,
class VALUE>
1887template <
class KEY,
class VALUE>
1888template <
class EQUAL>
1895 if (d_head_p == NULL) {
1896 d_head_p =
new (*d_allocator_p)
1902 d_tail_p = d_head_p;
1909 for (; curNode != NULL; curNode = curNode->
next()) {
1910 if (equal(curNode->
key(), key)) {
1911 curNode->
value() = value;
1912 if (e_BUCKETSCOPE_FIRST == scope) {
1927 d_tail_p->setNext(newNode);
1928 d_tail_p = d_tail_p->next();
1933template <
class KEY,
class VALUE>
1934template <
class EQUAL>
1940 if (d_head_p == NULL) {
1941 d_head_p =
new (*d_allocator_p)
1947 d_tail_p = d_head_p;
1952 for (; curNode != NULL; curNode = curNode->
next()) {
1953 if (equal(curNode->
key(), key)) {
1954#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1957 curNode->
value() = value;
1968 d_tail_p->setNext(newNode);
1969 d_tail_p = d_tail_p->next();
1975template <
class KEY,
class VALUE>
1982template <
class KEY,
class VALUE>
1990template <
class KEY,
class VALUE>
1997template <
class KEY,
class VALUE>
2007template <
class KEY,
class VALUE>
2012 return d_allocator_p;
2062: d_lockElement_p(lockElementPtr)
2077 if (d_lockElement_p) {
2079 d_lockElement_p = NULL;
2092: d_lockElement_p(lockElementPtr)
2107 if (d_lockElement_p) {
2109 d_lockElement_p = NULL;
2122: d_firstLock_p(firstLock_p)
2132 for (
unsigned i = d_numLocked; i > 0; --i)
2134 d_firstLock_p[i - 1].
unlockW();
2143 BSLS_ASSERT(lock_p == (d_firstLock_p + d_numLocked));
2154template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2158 bsl::size_t numBuckets,
2159 bsl::size_t numStripes)
2163 if (numBuckets < 2) {
2166 if (numBuckets < numStripes) {
2167 numBuckets = numStripes;
2169 numBuckets = powerCeil(numBuckets);
2173template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2175bool StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::alwaysTrue(
2181template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2183bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::powerCeil(
2198template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2200void StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::checkRehash()
2202 float loadF = loadFactor();
2203 if (d_maxLoadFactor < loadF && canRehash()) {
2204 int ratio =
static_cast<int>(loadF / d_maxLoadFactor);
2205 int growthFactor = 2;
2206 while (growthFactor < ratio) {
2209 bsl::size_t newNumBuckets = d_numBuckets * growthFactor;
2210 rehash(newNumBuckets);
2214template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2216bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::erase(
2220 return eraseIf(key, scope, alwaysTrue);
2223template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2224template <
class RANDOM_ITER>
2225bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::eraseBulk(
2232 bool eraseAll = scope == e_SCOPE_ALL;
2233 bsl::size_t count = 0;
2235 int dataSize =
static_cast<int>(last - first);
2239 for (
int i = 0; i < dataSize; ++i) {
2240 sortIdxs[i].d_hashVal = d_hasher(first[i]);
2241 bsl::size_t bucketIdx =
2244 sortIdxs[i].d_stripeIdx =
static_cast<int>(bucketToStripe(bucketIdx));
2245 sortIdxs[i].d_dataIdx = i;
2248 bsl::sort(sortIdxs.begin(), sortIdxs.end());
2253 for (
int j = 0; j < dataSize;) {
2254 curStripeIdx = sortIdxs[j].d_stripeIdx;
2255 LockElement& lockElement = d_locks_p[curStripeIdx];
2256 lockElement.lockW();
2257 LEWGuard guard(&lockElement);
2258 for (; j < dataSize && sortIdxs[j].d_stripeIdx == curStripeIdx; ++j) {
2259 int dataIdx = sortIdxs[j].d_dataIdx;
2260 bsl::size_t bucketIdx =
2262 sortIdxs[j].d_hashVal,
2265 StripedUnorderedContainerImpl_Bucket<KEY, VALUE> &bucket =
2266 d_buckets[bucketIdx];
2268 const KEY& key = first[dataIdx];
2270 Node **prevNodeAddress = bucket.headAddress();
2271 Node *prevNode = NULL;
2272 while (*prevNodeAddress) {
2273 Node *node = *prevNodeAddress;
2274 if (d_comparator(node->key(), key)) {
2275 *prevNodeAddress = node->next();
2276 if (bucket.tail() == node) {
2277 bucket.setTail(prevNode);
2279 d_allocator_p->deleteObject(node);
2280 bucket.incrementSize(-1);
2281 d_numElements.addRelaxed(-1);
2289 prevNodeAddress = node->nextAddress();
2298template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2299bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::eraseIf(
2302 const EraseIfValuePredicate& predicate)
2304 bool eraseAll = scope == e_SCOPE_ALL;
2305 bsl::size_t bucketIdx;
2306 LEWGuard guard(lockWrite(&bucketIdx, key));
2308 StripedUnorderedContainerImpl_Bucket<KEY, VALUE> &bucket =
2309 d_buckets[bucketIdx];
2311 typedef StripedUnorderedContainerImpl_Node<KEY, VALUE> Node;
2313 bsl::size_t count = 0;
2315 Node **prevNodeAddress = bucket.headAddress();
2316 Node *prevNode = NULL;
2317 while (*prevNodeAddress) {
2318 Node *node = *prevNodeAddress;
2319 if (d_comparator(node->key(), key) && predicate(node->value())) {
2320 *prevNodeAddress = node->next();
2321 if (bucket.tail() == node) {
2322 bucket.setTail(prevNode);
2324 d_allocator_p->deleteObject(node);
2325 bucket.incrementSize(-1);
2326 d_numElements.addRelaxed(-1);
2334 prevNodeAddress = node->nextAddress();
2340template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2342bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insert(
2345 Multiplicity multiplicity)
2347 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2349 bsl::size_t bucketIdx;
2350 LEWGuard guard(lockWrite(&bucketIdx, key));
2352 bsl::size_t ret = 0;
2355 Node *node =
new (*d_allocator_p)
2356 StripedUnorderedContainerImpl_Node<KEY, VALUE>(key,
2360 d_buckets[bucketIdx].addNode(node);
2364 ret = d_buckets[bucketIdx].setValue(
2374 d_numElements.addRelaxed(1);
2379template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2381bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insert(
2384 Multiplicity multiplicity)
2386 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2388 bsl::size_t bucketIdx;
2389 LEWGuard guard(lockWrite(&bucketIdx, key));
2391 bsl::size_t ret = 0;
2394 Node *node =
new (*d_allocator_p)
2396 d_buckets[bucketIdx].addNode(node);
2400 ret = d_buckets[bucketIdx].setValue(
2409 d_numElements.addRelaxed(1);
2414template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2415template <
class RANDOM_ITER>
2416bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insertBulk(
2419 Multiplicity multiplicity)
2423 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2424 bsl::size_t count = 0;
2425 int dataSize =
static_cast<int>(last - first);
2431 for (
int i = 0; i < dataSize; ++i) {
2432 sortIdxs[i].d_hashVal = d_hasher(first[i].first);
2433 bsl::size_t bucketIdx =
2436 sortIdxs[i].d_stripeIdx =
static_cast<int>(bucketToStripe(bucketIdx));
2437 sortIdxs[i].d_dataIdx = i;
2440 bsl::sort(sortIdxs.begin(), sortIdxs.end());
2445 for (
int j = 0; j < dataSize;) {
2446 curStripeIdx = sortIdxs[j].d_stripeIdx;
2447 LockElement& lockElement = d_locks_p[curStripeIdx];
2448 lockElement.lockW();
2449 LEWGuard guard(&lockElement);
2450 for (; j < dataSize && sortIdxs[j].d_stripeIdx == curStripeIdx; ++j) {
2451 int dataIdx = sortIdxs[j].d_dataIdx;
2452 bsl::size_t bucketIdx =
2454 sortIdxs[j].d_hashVal,
2456 const KEY& key = first[dataIdx].first;
2457 const VALUE& value = first[dataIdx].second;
2462 StripedUnorderedContainerImpl_Node<KEY, VALUE> *node =
2463 new (*d_allocator_p)
2464 StripedUnorderedContainerImpl_Node<KEY, VALUE>(
2469 d_buckets[bucketIdx].addNode(node);
2471 d_numElements.addRelaxed(1);
2473 bsl::size_t ret = d_buckets[bucketIdx].setValue(
2477 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>::
2478 e_BUCKETSCOPE_FIRST);
2481 d_numElements.addRelaxed(1);
2490template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2491int StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::setComputedValue(
2493 const VisitorFunction& visitor,
2496 typedef StripedUnorderedContainerImpl_Bucket<KEY, VALUE> BucketClass;
2497 typename BucketClass::BucketScope setAll = scope == e_SCOPE_ALL
2498 ? BucketClass::e_BUCKETSCOPE_ALL
2499 : BucketClass::e_BUCKETSCOPE_FIRST;
2501 bsl::size_t bucketIdx;
2502 LEWGuard guard(lockWrite(&bucketIdx, key));
2504 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket =
2505 d_buckets[bucketIdx];
2508 StripedUnorderedContainerImpl_Node<KEY, VALUE> *curNode = bucket.head();
2509 for (; curNode != NULL; curNode = curNode->next()) {
2510 if (d_comparator(curNode->key(), key)) {
2511 bool ret = visitor(&curNode->value(), key);
2512 if (
false == setAll) {
2513 return ret ? 1 : -1;
2526 StripedUnorderedContainerImpl_Node<KEY, VALUE> *addNode =
2527 new (*d_allocator_p)
2528 StripedUnorderedContainerImpl_Node<KEY, VALUE>(key,
2533 StripedUnorderedContainerImpl_Node<KEY, VALUE>,
2535 proctor(addNode, d_allocator_p);
2537 visitor(&addNode->value(), key);
2541 if (bucket.head() == NULL) {
2542 bucket.setHead(addNode);
2543 bucket.setTail(addNode);
2546 bucket.tail()->setNext(addNode);
2547 bucket.setTail(addNode);
2549 d_numElements.addRelaxed(1);
2550 bucket.incrementSize(1);
2556template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2558bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::setValue(
2563 typedef StripedUnorderedContainerImpl_Bucket<KEY, VALUE> BucketClass;
2564 typename BucketClass::BucketScope setAll = scope == e_SCOPE_ALL
2565 ? BucketClass::e_BUCKETSCOPE_ALL
2566 : BucketClass::e_BUCKETSCOPE_FIRST;
2568 bsl::size_t bucketIdx;
2569 LEWGuard guard(lockWrite(&bucketIdx, key));
2571 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket =
2572 d_buckets[bucketIdx];
2574 bsl::size_t count = bucket.setValue(key, d_comparator, value, setAll);
2577 d_numElements.addRelaxed(1);
2584template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2587StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::bucketIndex(
2589 bsl::size_t numBuckets)
const
2591 bsl::size_t hashVal = d_hasher(key);
2592 bsl::size_t bucketIdx =
2597template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2600StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::bucketToStripe(
2601 bsl::size_t bucketIndex)
const
2603 return bucketIndex & d_hashMask;
2606template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2607template <
class VECTOR>
2610StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::getValueImpl(
2612 const KEY& key)
const
2614 static const bool isVector =
2616#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
2626 bsl::size_t bucketIdx;
2627 LERGuard guard(lockRead(&bucketIdx, key));
2629 bsl::size_t count = 0;
2630 const StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket = d_buckets[
2633 StripedUnorderedContainerImpl_Node<KEY, VALUE> *curNode = bucket.head();
2634 for (; curNode != NULL; curNode = curNode->next()) {
2635 if (d_comparator(curNode->key(), key)) {
2636 valuesPtr->push_back(curNode->value());
2643template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2645StripedUnorderedContainerImpl_LockElement *
2646StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::lockRead(
2647 bsl::size_t *bucketIdx,
2648 const KEY& key)
const
2651 bsl::size_t hashVal = d_hasher(key);
2652 bsl::size_t numBuckets = d_numBuckets;
2653 bsl::size_t bucketIndex =
2655 bsl::size_t stripeIdx = bucketToStripe(bucketIndex);
2656 LockElement& lockElement = d_locks_p[stripeIdx];
2657 lockElement.lockR();
2659 if (numBuckets != d_numBuckets) {
2663 *bucketIdx = bucketIndex;
2664 return &lockElement;
2667template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2669StripedUnorderedContainerImpl_LockElement *
2670StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::lockWrite(
2671 bsl::size_t *bucketIdx,
2672 const KEY& key)
const
2675 bsl::size_t hashVal = d_hasher(key);
2676 bsl::size_t numBuckets = d_numBuckets;
2677 bsl::size_t bucketIndex =
2679 bsl::size_t stripeIdx = bucketToStripe(bucketIndex);
2680 LockElement& lockElement = d_locks_p[stripeIdx];
2681 lockElement.lockW();
2684 if (numBuckets != d_numBuckets) {
2688 *bucketIdx = bucketIndex;
2689 return &lockElement;
2693template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2698 float maxLoadFactor,
2699 bsl::size_t numInitialBuckets,
2700 bsl::size_t numStripes,
2702: d_numStripes(powerCeil(numStripes))
2703, d_numBuckets(adjustBuckets(numInitialBuckets, d_numStripes))
2704, d_hashMask(d_numStripes - 1)
2705, d_maxLoadFactor(maxLoadFactor)
2710, d_buckets(d_numBuckets, basicAllocator)
2711, d_allocator_p(
bslma::Default::allocator(basicAllocator))
2719 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2724template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2728 bsl::size_t numInitialBuckets,
2729 bsl::size_t numStripes,
2731: d_numStripes(powerCeil(numStripes))
2732, d_numBuckets(adjustBuckets(numInitialBuckets, d_numStripes))
2733, d_hashMask(d_numStripes - 1)
2734, d_maxLoadFactor(1.0)
2739, d_buckets(d_numBuckets, basicAllocator)
2740, d_allocator_p(
bslma::Default::allocator(basicAllocator))
2748 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2753template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2758 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2759 bslma::DestructionUtil::destroy(&d_locks_p[i]);
2761 d_allocator_p->deallocate(d_locks_p);
2765template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2770 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2771 d_locks_p[i].lockW();
2773 for (bsl::size_t j = 0; j < d_numBuckets; ++j) {
2774 d_buckets[j].clear();
2777 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2778 d_locks_p[i].unlockW();
2782template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2787 int oldState = d_state.load();
2788 int newState = oldState & ~k_REHASH_ENABLED;
2789 if (oldState == d_state.testAndSwap(oldState, newState)) {
2795template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2800 int oldState = d_state.load();
2801 int newState = oldState | k_REHASH_ENABLED;
2802 if (oldState == d_state.testAndSwap(oldState, newState)) {
2808template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2813 return erase(key, e_SCOPE_ALL);
2816template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2822 return eraseIf(key, e_SCOPE_ALL, predicate);
2825template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2826template <
class RANDOM_ITER>
2835 return eraseBulk(first, last, e_SCOPE_ALL);
2838template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2839template <
class RANDOM_ITER>
2848 return eraseBulk(first, last, e_SCOPE_FIRST);
2851template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2856 return erase(key, e_SCOPE_FIRST);
2859template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2866 return eraseIf(key, e_SCOPE_FIRST, predicate);
2869template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2875 insert(key, value, e_INSERT_ALWAYS);
2878template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2887template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2888template <
class RANDOM_ITER>
2896 insertBulk(first, last, e_INSERT_ALWAYS);
2899template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2900template <
class RANDOM_ITER>
2909 return insertBulk(first, last, e_INSERT_UNIQUE);
2912template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2919 return insert(key, value, e_INSERT_UNIQUE);
2922template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2932template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2934 bsl::size_t numBuckets)
2938 if (numBuckets < 2) {
2941 if (numBuckets < d_numStripes) {
2942 numBuckets = d_numStripes;
2944 numBuckets = powerCeil(numBuckets);
2946 if (numBuckets <= d_numBuckets) {
2955 if (!rehashGuard.
holdsLock() || numBuckets <= d_numBuckets.loadRelaxed()) {
2966 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2967 locksGuard.
lock(d_locks_p + i);
2973 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
2980 bucket.
head(); curNode != NULL;) {
2984 bsl::size_t newBucketIdx = bucketIndex(curNode->key(),
2986 curNode->setNext(NULL);
2987 newBuckets[newBucketIdx].addNode(curNode);
2996 d_buckets.swap(newBuckets);
2999 d_numBuckets = numBuckets;
3002template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3009 return setComputedValue(key, visitor, e_SCOPE_ALL);
3012template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3019 return setComputedValue(key, visitor, e_SCOPE_FIRST);
3022template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3029 return setValue(key, value, e_SCOPE_ALL);
3032template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3039 return setValue(key, value, e_SCOPE_FIRST);
3042template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3049 bsl::size_t bucketIdx;
3050 LEWGuard guard(lockWrite(&bucketIdx, key));
3053 d_buckets[bucketIdx];
3055 bsl::size_t count = bucket.
setValue(key,
3060 d_numElements.addRelaxed(1);
3066template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3072 return visit(key, visitor);
3075template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3081 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
3083 lockElement.
lockW();
3089 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
3094 bucket.
head(); curNode != NULL;
3095 curNode = curNode->next()) {
3097 bool ret = visitor(&(curNode->value()), curNode->key());
3107template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3113 bsl::size_t bucketIdx;
3114 LEWGuard guard(lockWrite(&bucketIdx, key));
3117 d_buckets[bucketIdx];
3122 for (; curNode != NULL; curNode = curNode->
next()) {
3123 if (d_comparator(curNode->
key(), key)) {
3125 bool ret = visitor(&curNode->
value(), key);
3135template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3140 return d_numBuckets;
3143template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3147 const KEY& key)
const
3149 return bucketIndex(key, d_numBuckets);
3152template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3155 bsl::size_t index)
const
3159 return d_buckets[index].size();
3162template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3166 return d_state == k_REHASH_ENABLED;
3169template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3173 for (bsl::size_t i = 0; i < d_numBuckets; ++i) {
3174 if (!d_buckets[i].empty()) {
3181template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3186 return d_comparator;
3189template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3193 const KEY& key)
const
3197 bsl::size_t bucketIdx;
3198 LERGuard guard(lockRead(&bucketIdx, key));
3204 for (; curNode != NULL; curNode = curNode->
next()) {
3205 if (d_comparator(curNode->
key(), key)) {
3206 *value = curNode->
value();
3213template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3217 const KEY& key)
const
3219 return getValueImpl(valuesPtr, key);
3222template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3225 std::vector<VALUE> *valuesPtr,
3226 const KEY& key)
const
3228 return getValueImpl(valuesPtr, key);
3231#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
3232template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3235 std::pmr::vector<VALUE> *valuesPtr,
3236 const KEY& key)
const
3238 return getValueImpl(valuesPtr, key);
3242template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3250template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3255 return d_state & k_REHASH_ENABLED;
3258template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3263 return static_cast<float>(d_numElements.loadRelaxed()) /
3264 static_cast<float>(d_numBuckets);
3267template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3272 return d_maxLoadFactor;
3275template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3280 return static_cast<bsl::size_t
>(d_numStripes);
3283template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3289 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
3291 lockElement.
lockR();
3297 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
3302 bucket.
head(); curNode != NULL;
3303 curNode = curNode->next()) {
3305 bool ret = visitor(curNode->value(), curNode->key());
3315template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3321 bsl::size_t bucketIdx;
3322 LERGuard guard(lockRead(&bucketIdx, key));
3325 d_buckets[bucketIdx];
3330 for (; curNode != NULL; curNode = curNode->
next()) {
3331 if (d_comparator(curNode->
key(), key)) {
3333 bool ret = visitor(curNode->
value(), key);
3342template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3347 return d_numElements.loadRelaxed();
3352template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3357 return d_allocator_p;
3365template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3375template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3380 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3381 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3382 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3383 lockElement.
lockR();
3386template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3391 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3392 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3393 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3394 lockElement.
lockW();
3397template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3402 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3403 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3404 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3408template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3413 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3414 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3415 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3424 const StripedUnorderedContainerImpl_SortItem& rhs)
3426 if (lhs.d_stripeIdx < rhs.d_stripeIdx) {
3429 if (
lhs.d_stripeIdx >
rhs.d_stripeIdx) {
3432 if (
lhs.d_dataIdx <
rhs.d_dataIdx) {
3440template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
Definition bdlcc_stripedunorderedcontainerimpl.h:1516
~StripedUnorderedContainerImpl_ArrayOfLocksWriteGuard()
Definition bdlcc_stripedunorderedcontainerimpl.h:2130
StripedUnorderedContainerImpl_ArrayOfLocksWriteGuard(StripedUnorderedContainerImpl_LockElement *firstLock_p)
Definition bdlcc_stripedunorderedcontainerimpl.h:2120
void lock(StripedUnorderedContainerImpl_LockElement *lock_p)
Definition bdlcc_stripedunorderedcontainerimpl.h:2140
Definition bdlcc_stripedunorderedcontainerimpl.h:365
void addNode(StripedUnorderedContainerImpl_Node< KEY, VALUE > *nodePtr)
Add the specified nodePtr node at the end of this bucket.
Definition bdlcc_stripedunorderedcontainerimpl.h:1815
StripedUnorderedContainerImpl_Node< KEY, VALUE > * tail() const
Return address of the tail (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:2000
void setSize(bsl::size_t value)
Set the size attribute of this bucket to the specified value.
Definition bdlcc_stripedunorderedcontainerimpl.h:1873
void setHead(StripedUnorderedContainerImpl_Node< KEY, VALUE > *value)
Definition bdlcc_stripedunorderedcontainerimpl.h:1865
BucketScope
Definition bdlcc_stripedunorderedcontainerimpl.h:400
@ e_BUCKETSCOPE_FIRST
Definition bdlcc_stripedunorderedcontainerimpl.h:402
@ e_BUCKETSCOPE_ALL
Definition bdlcc_stripedunorderedcontainerimpl.h:403
~StripedUnorderedContainerImpl_Bucket()
Destroy this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1807
void setTail(StripedUnorderedContainerImpl_Node< KEY, VALUE > *value)
Definition bdlcc_stripedunorderedcontainerimpl.h:1881
BSLMF_NESTED_TRAIT_DECLARATION(StripedUnorderedContainerImpl_Bucket, bslma::UsesBslmaAllocator)
bsl::size_t size() const
Return the current number of elements in this bucket.
Definition bdlcc_stripedunorderedcontainerimpl.h:1992
StripedUnorderedContainerImpl_Node< KEY, VALUE > ** headAddress()
Return the address of the head (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:1850
void incrementSize(int amount)
Definition bdlcc_stripedunorderedcontainerimpl.h:1857
StripedUnorderedContainerImpl_Node< KEY, VALUE > * head() const
Return the head (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:1985
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2009
bsl::size_t setValue(const KEY &key, const EQUAL &equal, const VALUE &value, BucketScope scope)
Definition bdlcc_stripedunorderedcontainerimpl.h:1889
bool empty() const
Definition bdlcc_stripedunorderedcontainerimpl.h:1977
void clear()
Empty StripedUnorderedContainerImpl_Bucket and delete all nodes.
Definition bdlcc_stripedunorderedcontainerimpl.h:1832
Definition bdlcc_stripedunorderedcontainerimpl.h:1446
StripedUnorderedContainerImpl_LockElementReadGuard(StripedUnorderedContainerImpl_LockElement *lockElementPtr)
Definition bdlcc_stripedunorderedcontainerimpl.h:2060
~StripedUnorderedContainerImpl_LockElementReadGuard()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:2069
void release()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:2075
Definition bdlcc_stripedunorderedcontainerimpl.h:1481
~StripedUnorderedContainerImpl_LockElementWriteGuard()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:2099
StripedUnorderedContainerImpl_LockElementWriteGuard(StripedUnorderedContainerImpl_LockElement *lockElementPtr)
Definition bdlcc_stripedunorderedcontainerimpl.h:2090
void release()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:2105
Definition bdlcc_stripedunorderedcontainerimpl.h:1390
void lockR()
Read lock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:2030
void unlockW()
Write unlock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:2048
void unlockR()
Read unlock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:2042
StripedUnorderedContainerImpl_LockElement()
Create an empty StripedUnorderedContainerImpl_LockElement object.
Definition bdlcc_stripedunorderedcontainerimpl.h:2022
void lockW()
Write lock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:2036
Definition bdlcc_stripedunorderedcontainerimpl.h:266
~StripedUnorderedContainerImpl_Node()
Destroy this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1705
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:1765
const KEY & key() const
Return a const reference to the key attribute of this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1740
void setNext(StripedUnorderedContainerImpl_Node *nextPtr)
Set this node's pointer-to-next-node to the specified nextPtr.
Definition bdlcc_stripedunorderedcontainerimpl.h:1724
StripedUnorderedContainerImpl_Node ** nextAddress()
Return the address of the pointer to the next node.
Definition bdlcc_stripedunorderedcontainerimpl.h:1717
StripedUnorderedContainerImpl_Node * next() const
Return the pointer to the next node.
Definition bdlcc_stripedunorderedcontainerimpl.h:1748
VALUE & value()
Definition bdlcc_stripedunorderedcontainerimpl.h:1732
Definition bdlcc_stripedunorderedcontainerimpl.h:222
bool holdsLock() const
Returns true if the constructor successfully set the rehash bit.
Definition bdlcc_stripedunorderedcontainerimpl.h:1613
~StripedUnorderedContainerImpl_RehashBitSetGuard()
Definition bdlcc_stripedunorderedcontainerimpl.h:1591
StripedUnorderedContainerImpl_RehashBitSetGuard(bsls::AtomicInt *state_p)
Definition bdlcc_stripedunorderedcontainerimpl.h:1583
Definition bdlcc_stripedunorderedcontainerimpl.h:1342
void unlockRead(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3400
void lockWrite(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3389
void lockRead(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3377
void unlockWrite(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3411
~StripedUnorderedContainerImpl_TestUtil()=default
StripedUnorderedContainerImpl_TestUtil(StripedUnorderedContainerImpl< KEY, VALUE, HASH, EQUAL > &hash)
Definition bdlcc_stripedunorderedcontainerimpl.h:3368
Definition bdlcc_stripedunorderedcontainerimpl.h:542
bsl::size_t getValue(VALUE *value, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3191
bsl::size_t bucketSize(bsl::size_t index) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3154
bool empty() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3171
StripedUnorderedContainerImpl_Node< KEY, VALUE > Node
Node in a bucket.
Definition bdlcc_stripedunorderedcontainerimpl.h:552
float loadFactor() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3261
bsl::size_t setValueFirst(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:3045
int update(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:3068
int visitReadOnly(const KEY &key, const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3317
float maxLoadFactor() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3270
bsl::size_t insertUnique(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2925
bsl::size_t setValueFirst(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:3035
bsl::size_t numStripes() const
Return the number of stripes in the hash.
Definition bdlcc_stripedunorderedcontainerimpl.h:3278
HASH hashFunction() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3245
bsl::function< bool(VALUE *, const KEY &)> VisitorFunction
Definition bdlcc_stripedunorderedcontainerimpl.h:567
bsl::size_t bucketIndex(const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3146
bsl::size_t insertBulkUnique(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2903
void rehash(bsl::size_t numBuckets)
Definition bdlcc_stripedunorderedcontainerimpl.h:2933
bsl::size_t insertUnique(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2915
bsl::pair< KEY, VALUE > KVType
Value type of a bulk insert entry.
Definition bdlcc_stripedunorderedcontainerimpl.h:555
int visit(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:3109
StripedUnorderedContainerImpl(StripedUnorderedContainerImplMaxLoadFactorFlag, float maxLoadFactor=1.0, bsl::size_t numInitialBuckets=k_DEFAULT_NUM_BUCKETS, bsl::size_t numStripes=k_DEFAULT_NUM_STRIPES, bslma::Allocator *basicAllocator=0)
Definition bdlcc_stripedunorderedcontainerimpl.h:2696
void disableRehash()
Prevent rehash until the enableRehash method is called.
Definition bdlcc_stripedunorderedcontainerimpl.h:2784
bool isRehashEnabled() const
Return true if rehash is enabled, or false otherwise.
Definition bdlcc_stripedunorderedcontainerimpl.h:3253
bsl::size_t eraseFirstIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedcontainerimpl.h:2862
StripedUnorderedContainerImpl(bsl::size_t numInitialBuckets=k_DEFAULT_NUM_BUCKETS, bsl::size_t numStripes=k_DEFAULT_NUM_STRIPES, bslma::Allocator *basicAllocator=0)
Definition bdlcc_stripedunorderedcontainerimpl.h:2727
void clear()
Definition bdlcc_stripedunorderedcontainerimpl.h:2767
void insertBulkAlways(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2890
bsl::size_t size() const
Return the current number of elements in this hash.
Definition bdlcc_stripedunorderedcontainerimpl.h:3345
bsl::size_t eraseFirst(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:2853
bsl::size_t eraseBulkFirst(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2842
void insertAlways(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2880
~StripedUnorderedContainerImpl()
Destroy this hash map. This method is not thread-safe.
Definition bdlcc_stripedunorderedcontainerimpl.h:2756
bsl::size_t setValueAll(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:3025
void insertAlways(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2871
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3355
int visitReadOnly(const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3284
int setComputedValueAll(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:3005
bsl::function< bool(const VALUE &)> EraseIfValuePredicate
Definition bdlcc_stripedunorderedcontainerimpl.h:591
void enableRehash()
Definition bdlcc_stripedunorderedcontainerimpl.h:2797
bool canRehash() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3164
bsl::size_t eraseAllIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedcontainerimpl.h:2818
friend class StripedUnorderedContainerImpl_LockElement
Definition bdlcc_stripedunorderedcontainerimpl.h:690
bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2829
int setComputedValueFirst(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:3015
bsl::function< bool(const VALUE &, const KEY &)> ReadOnlyVisitorFunction
Definition bdlcc_stripedunorderedcontainerimpl.h:581
bsl::size_t bucketCount() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3138
bsl::size_t getValue(std::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3224
@ k_DEFAULT_NUM_STRIPES
Definition bdlcc_stripedunorderedcontainerimpl.h:548
@ k_DEFAULT_NUM_BUCKETS
Definition bdlcc_stripedunorderedcontainerimpl.h:547
EQUAL equalFunction() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3184
bsl::size_t getValue(bsl::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3215
int visit(const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:3076
bsl::size_t eraseAll(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:2810
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_pair.h:1280
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
virtual void * allocate(size_type size)=0
Definition bslma_destructorproctor.h:259
void release()
Definition bslma_destructorproctor.h:328
Definition bslma_rawdeleterproctor.h:242
Definition bslmf_movableref.h:752
Definition bslmt_readerwritermutex.h:244
void unlockRead()
Definition bslmt_readerwritermutex.h:380
void unlockWrite()
Definition bslmt_readerwritermutex.h:386
void lockRead()
Definition bslmt_readerwritermutex.h:350
void lockWrite()
Definition bslmt_readerwritermutex.h:356
Definition bsls_atomic.h:744
int testAndSwap(int compareValue, int swapValue)
Definition bsls_atomic.h:1723
Definition bsls_atomic.h:1205
Definition bsls_atomic.h:1050
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#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
bool operator<(const StripedUnorderedContainerImpl_SortItem &lhs, const StripedUnorderedContainerImpl_SortItem &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition baljsn_encoder_testtypes.h:76
Definition bdlcc_stripedunorderedcontainerimpl.h:532
Definition bdlcc_stripedunorderedcontainerimpl.h:208
static const int k_REHASH_IN_PROGRESS
Definition bdlcc_stripedunorderedcontainerimpl.h:210
static const int k_REHASH_ENABLED
Definition bdlcc_stripedunorderedcontainerimpl.h:211
Definition bdlcc_stripedunorderedcontainerimpl.h:1557
int d_stripeIdx
Definition bdlcc_stripedunorderedcontainerimpl.h:1560
int d_dataIdx
Definition bdlcc_stripedunorderedcontainerimpl.h:1561
bsl::size_t d_hashVal
Definition bdlcc_stripedunorderedcontainerimpl.h:1562
Definition bslstl_equalto.h:316
Definition bslstl_hash.h:495
Definition bslmf_issame.h:146
static std::size_t computeBucketIndex(std::size_t hashCode, std::size_t numBuckets)
Definition bslalg_hashtableimputil.h:858
static void moveConstruct(TARGET_TYPE *address, TARGET_TYPE &original, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1660
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1244
static Allocator * defaultAllocator()
Definition bslma_default.h:905
Definition bslma_usesbslmaallocator.h:344
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
Definition bsls_objectbuffer.h:277
TYPE * address()
Definition bsls_objectbuffer.h:335
TYPE & object()
Definition bsls_objectbuffer.h:352