8#ifndef INCLUDED_BDLCC_STRIPEDUNORDEREDCONTAINERIMPL
9#define INCLUDED_BDLCC_STRIPEDUNORDEREDCONTAINERIMPL
148#include <bdlscm_version.h>
178#include <bsl_algorithm.h>
179#include <bsl_cstddef.h>
180#include <bsl_functional.h>
182#include <bsl_vector.h>
183#include <bsl_iostream.h>
184#include <bsl_sstream.h>
195class StripedUnorderedContainerImpl;
205template <
class KEY,
class VALUE>
279 const KEY&
key()
const;
285 const VALUE&
value()
const;
303template <
class KEY,
class VALUE>
311 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
388 void setSize(bsl::size_t value);
412 template <
class EQUAL>
413 bsl::size_t
setValue(
const KEY& key,
427 template <
class EQUAL>
428 bsl::size_t
setValue(
const KEY& key,
442 bsl::size_t
size()
const;
472template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
523 static const int k_REHASH_IN_PROGRESS = 1;
524 static const int k_REHASH_ENABLED = 2;
528 #if BSLS_PLATFORM_CPU_X86 || BSLS_PLATFORM_CPU_X86_64
529 k_PREFETCH_ENABLED = 1,
531 k_PREFETCH_ENABLED = 0,
534 k_EFFECTIVE_CACHELINE_SIZE = (1 + k_PREFETCH_ENABLED) *
562 typedef StripedUnorderedContainerImpl_LockElementReadGuard LERGuard;
563 typedef StripedUnorderedContainerImpl_LockElementWriteGuard LEWGuard;
568 bsl::size_t d_numStripes;
571 bsl::size_t d_numBuckets;
576 bsl::size_t d_hashMask;
579 float d_maxLoadFactor;
592 const char d_statePad[k_INT_PADDING];
598 const char d_numElementsPad[k_INT_PADDING];
606 LockElement *d_locks_p;
630 static bsl::size_t adjustBuckets(bsl::size_t numBuckets,
634 static bool alwaysTrue(
const VALUE&);
637 static bsl::size_t powerCeil(bsl::size_t num);
651 bsl::size_t erase(
const KEY& key, Scope scope);
663 template <
class RANDOM_ITER>
664 bsl::size_t eraseBulk(RANDOM_ITER first,
676 bsl::size_t eraseIf(
const KEY& key,
696 bsl::size_t insert(
const KEY& key,
698 Multiplicity multiplicity);
699 bsl::size_t insert(
const KEY& key,
701 Multiplicity multiplicity);
724 template <
class RANDOM_ITER>
725 bsl::size_t insertBulk(RANDOM_ITER first,
727 Multiplicity multiplicity);
750 int setComputedValue(
const KEY& key,
772 bsl::size_t setValue(
const KEY& key,
784 bsl::size_t bucketIndex(
const KEY& key, bsl::size_t numBuckets)
const;
787 bsl::size_t bucketToStripe(bsl::size_t bucketIndex)
const;
793 template <
class VECTOR>
794 bsl::size_t getValueImpl(VECTOR *valuesPtr,
const KEY& key)
const;
800 LockElement *lockRead(bsl::size_t *bucketIdx,
const KEY& key)
const;
806 LockElement *lockWrite(bsl::size_t *bucketIdx,
const KEY& key)
const;
862 template <
class RANDOM_ITER>
874 template <
class RANDOM_ITER>
908 template <
class RANDOM_ITER>
920 template <
class RANDOM_ITER>
1120 bsl::size_t
getValue(VALUE *value,
const KEY& key)
const;
1123 bsl::size_t
getValue(std::vector<VALUE> *valuesPtr,
const KEY& key)
const;
1124#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1125 bsl::size_t
getValue(std::pmr::vector<VALUE> *valuesPtr,
const KEY& key)
1210template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1267 #if BSLS_PLATFORM_CPU_X86 || BSLS_PLATFORM_CPU_X86_64
1268 k_PREFETCH_ENABLED = 1,
1270 k_PREFETCH_ENABLED = 0,
1273 k_EFFECTIVE_CACHELINE_SIZE = (1 + k_PREFETCH_ENABLED) *
1276 k_LOCK_PADDING = k_EFFECTIVE_CACHELINE_SIZE >=
sizeof(
LockType) ?
1277 k_EFFECTIVE_CACHELINE_SIZE -
sizeof(
LockType) :
1278 2 * k_EFFECTIVE_CACHELINE_SIZE -
sizeof(
LockType)
1283 const char d_pad[k_LOCK_PADDING];
1403template <
class KEY,
class VALUE>
1412, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1425template <
class KEY,
class VALUE>
1434, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1441 VALUE& dummy =
value;
1448template <
class KEY,
class VALUE>
1455, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1467template <
class KEY,
class VALUE>
1473 bslma::DestructionUtil::destroy(d_key.address());
1474 bslma::DestructionUtil::destroy(d_value.address());
1479template <
class KEY,
class VALUE>
1487template <
class KEY,
class VALUE>
1495template <
class KEY,
class VALUE>
1499 return d_value.object();
1503template <
class KEY,
class VALUE>
1507 return d_key.object();
1510template <
class KEY,
class VALUE>
1518template <
class KEY,
class VALUE>
1522 return d_value.object();
1527template <
class KEY,
class VALUE>
1532 return d_allocator_p;
1540template <
class KEY,
class VALUE>
1548, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1552template <
class KEY,
class VALUE>
1559: d_head_p(MoveUtil::move(MoveUtil::access(original).d_head_p))
1560, d_tail_p(MoveUtil::move(MoveUtil::access(original).d_tail_p))
1561, d_size( MoveUtil::access(original).d_size)
1562, d_allocator_p(MoveUtil::access(original).d_allocator_p)
1564 MoveUtil::access(original).d_head_p = NULL;
1565 MoveUtil::access(original).d_tail_p = NULL;
1566 MoveUtil::access(original).d_size = 0;
1569template <
class KEY,
class VALUE>
1578template <
class KEY,
class VALUE>
1585 if (d_head_p == NULL) {
1595template <
class KEY,
class VALUE>
1604 d_allocator_p->deleteObject(curNode);
1612template <
class KEY,
class VALUE>
1620template <
class KEY,
class VALUE>
1628template <
class KEY,
class VALUE>
1636template <
class KEY,
class VALUE>
1644template <
class KEY,
class VALUE>
1652template <
class KEY,
class VALUE>
1653template <
class EQUAL>
1660 if (d_head_p == NULL) {
1661 d_head_p =
new (*d_allocator_p)
1667 d_tail_p = d_head_p;
1674 for (; curNode != NULL; curNode = curNode->
next()) {
1675 if (equal(curNode->
key(), key)) {
1676 curNode->
value() = value;
1677 if (e_BUCKETSCOPE_FIRST == scope) {
1692 d_tail_p->setNext(newNode);
1693 d_tail_p = d_tail_p->next();
1698template <
class KEY,
class VALUE>
1699template <
class EQUAL>
1705 if (d_head_p == NULL) {
1706 d_head_p =
new (*d_allocator_p)
1712 d_tail_p = d_head_p;
1717 for (; curNode != NULL; curNode = curNode->
next()) {
1718 if (equal(curNode->
key(), key)) {
1719#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1722 curNode->
value() = value;
1733 d_tail_p->setNext(newNode);
1734 d_tail_p = d_tail_p->next();
1740template <
class KEY,
class VALUE>
1747template <
class KEY,
class VALUE>
1755template <
class KEY,
class VALUE>
1762template <
class KEY,
class VALUE>
1772template <
class KEY,
class VALUE>
1777 return d_allocator_p;
1827: d_lockElement_p(lockElementPtr)
1842 if (d_lockElement_p) {
1844 d_lockElement_p = NULL;
1857: d_lockElement_p(lockElementPtr)
1872 if (d_lockElement_p) {
1874 d_lockElement_p = NULL;
1883template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1887 bsl::size_t numBuckets,
1888 bsl::size_t numStripes)
1892 if (numBuckets < 2) {
1895 if (numBuckets < numStripes) {
1896 numBuckets = numStripes;
1898 numBuckets = powerCeil(numBuckets);
1902template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1904bool StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::alwaysTrue(
1910template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1912bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::powerCeil(
1927template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1929void StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::checkRehash()
1931 float loadF = loadFactor();
1932 if (d_maxLoadFactor < loadF && canRehash()) {
1933 int ratio =
static_cast<int>(loadF / d_maxLoadFactor);
1934 int growthFactor = 2;
1935 while (growthFactor < ratio) {
1938 bsl::size_t newNumBuckets = d_numBuckets * growthFactor;
1939 rehash(newNumBuckets);
1943template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1945bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::erase(
1949 return eraseIf(key, scope, alwaysTrue);
1952template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
1953template <
class RANDOM_ITER>
1954bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::eraseBulk(
1961 bool eraseAll = scope == e_SCOPE_ALL;
1962 bsl::size_t count = 0;
1964 int dataSize =
static_cast<int>(last - first);
1968 for (
int i = 0; i < dataSize; ++i) {
1969 sortIdxs[i].d_hashVal = d_hasher(first[i]);
1970 bsl::size_t bucketIdx =
1973 sortIdxs[i].d_stripeIdx =
static_cast<int>(bucketToStripe(bucketIdx));
1974 sortIdxs[i].d_dataIdx = i;
1977 bsl::sort(sortIdxs.begin(), sortIdxs.end());
1982 for (
int j = 0; j < dataSize;) {
1983 curStripeIdx = sortIdxs[j].d_stripeIdx;
1984 LockElement& lockElement = d_locks_p[curStripeIdx];
1985 lockElement.lockW();
1986 LEWGuard guard(&lockElement);
1987 for (; j < dataSize && sortIdxs[j].d_stripeIdx == curStripeIdx; ++j) {
1988 int dataIdx = sortIdxs[j].d_dataIdx;
1989 bsl::size_t bucketIdx =
1991 sortIdxs[j].d_hashVal,
1994 StripedUnorderedContainerImpl_Bucket<KEY, VALUE> &bucket =
1995 d_buckets[bucketIdx];
1997 const KEY& key = first[dataIdx];
1999 Node **prevNodeAddress = bucket.headAddress();
2000 Node *prevNode = NULL;
2001 while (*prevNodeAddress) {
2002 Node *node = *prevNodeAddress;
2003 if (d_comparator(node->key(), key)) {
2004 *prevNodeAddress = node->next();
2005 if (bucket.tail() == node) {
2006 bucket.setTail(prevNode);
2008 d_allocator_p->deleteObject(node);
2009 bucket.incrementSize(-1);
2010 d_numElements.addRelaxed(-1);
2018 prevNodeAddress = node->nextAddress();
2027template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2028bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::eraseIf(
2031 const EraseIfValuePredicate& predicate)
2033 bool eraseAll = scope == e_SCOPE_ALL;
2034 bsl::size_t bucketIdx;
2035 LEWGuard guard(lockWrite(&bucketIdx, key));
2037 StripedUnorderedContainerImpl_Bucket<KEY, VALUE> &bucket =
2038 d_buckets[bucketIdx];
2040 typedef StripedUnorderedContainerImpl_Node<KEY, VALUE> Node;
2042 bsl::size_t count = 0;
2044 Node **prevNodeAddress = bucket.headAddress();
2045 Node *prevNode = NULL;
2046 while (*prevNodeAddress) {
2047 Node *node = *prevNodeAddress;
2048 if (d_comparator(node->key(), key) && predicate(node->value())) {
2049 *prevNodeAddress = node->next();
2050 if (bucket.tail() == node) {
2051 bucket.setTail(prevNode);
2053 d_allocator_p->deleteObject(node);
2054 bucket.incrementSize(-1);
2055 d_numElements.addRelaxed(-1);
2063 prevNodeAddress = node->nextAddress();
2069template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2071bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insert(
2074 Multiplicity multiplicity)
2076 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2078 bsl::size_t bucketIdx;
2079 LEWGuard guard(lockWrite(&bucketIdx, key));
2081 bsl::size_t ret = 0;
2084 Node *node =
new (*d_allocator_p)
2085 StripedUnorderedContainerImpl_Node<KEY, VALUE>(key,
2089 d_buckets[bucketIdx].addNode(node);
2093 ret = d_buckets[bucketIdx].setValue(
2103 d_numElements.addRelaxed(1);
2108template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2110bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insert(
2113 Multiplicity multiplicity)
2115 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2117 bsl::size_t bucketIdx;
2118 LEWGuard guard(lockWrite(&bucketIdx, key));
2120 bsl::size_t ret = 0;
2123 Node *node =
new (*d_allocator_p)
2125 d_buckets[bucketIdx].addNode(node);
2129 ret = d_buckets[bucketIdx].setValue(
2138 d_numElements.addRelaxed(1);
2143template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2144template <
class RANDOM_ITER>
2145bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::insertBulk(
2148 Multiplicity multiplicity)
2152 bool insertAlways = multiplicity == e_INSERT_ALWAYS;
2153 bsl::size_t count = 0;
2154 int dataSize =
static_cast<int>(last - first);
2160 for (
int i = 0; i < dataSize; ++i) {
2161 sortIdxs[i].d_hashVal = d_hasher(first[i].first);
2162 bsl::size_t bucketIdx =
2165 sortIdxs[i].d_stripeIdx =
static_cast<int>(bucketToStripe(bucketIdx));
2166 sortIdxs[i].d_dataIdx = i;
2169 bsl::sort(sortIdxs.begin(), sortIdxs.end());
2174 for (
int j = 0; j < dataSize;) {
2175 curStripeIdx = sortIdxs[j].d_stripeIdx;
2176 LockElement& lockElement = d_locks_p[curStripeIdx];
2177 lockElement.lockW();
2178 LEWGuard guard(&lockElement);
2179 for (; j < dataSize && sortIdxs[j].d_stripeIdx == curStripeIdx; ++j) {
2180 int dataIdx = sortIdxs[j].d_dataIdx;
2181 bsl::size_t bucketIdx =
2183 sortIdxs[j].d_hashVal,
2185 const KEY& key = first[dataIdx].first;
2186 const VALUE& value = first[dataIdx].second;
2191 StripedUnorderedContainerImpl_Node<KEY, VALUE> *node =
2192 new (*d_allocator_p)
2193 StripedUnorderedContainerImpl_Node<KEY, VALUE>(
2198 d_buckets[bucketIdx].addNode(node);
2200 d_numElements.addRelaxed(1);
2202 bsl::size_t ret = d_buckets[bucketIdx].setValue(
2206 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>::
2207 e_BUCKETSCOPE_FIRST);
2210 d_numElements.addRelaxed(1);
2219template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2220int StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::setComputedValue(
2222 const VisitorFunction& visitor,
2225 typedef StripedUnorderedContainerImpl_Bucket<KEY, VALUE> BucketClass;
2226 typename BucketClass::BucketScope setAll = scope == e_SCOPE_ALL
2227 ? BucketClass::e_BUCKETSCOPE_ALL
2228 : BucketClass::e_BUCKETSCOPE_FIRST;
2230 bsl::size_t bucketIdx;
2231 LEWGuard guard(lockWrite(&bucketIdx, key));
2233 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket =
2234 d_buckets[bucketIdx];
2237 StripedUnorderedContainerImpl_Node<KEY, VALUE> *curNode = bucket.head();
2238 for (; curNode != NULL; curNode = curNode->next()) {
2239 if (d_comparator(curNode->key(), key)) {
2240 bool ret = visitor(&curNode->value(), key);
2241 if (
false == setAll) {
2242 return ret ? 1 : -1;
2255 StripedUnorderedContainerImpl_Node<KEY, VALUE> *addNode =
2256 new (*d_allocator_p)
2257 StripedUnorderedContainerImpl_Node<KEY, VALUE>(key,
2262 StripedUnorderedContainerImpl_Node<KEY, VALUE>,
2264 proctor(addNode, d_allocator_p);
2266 visitor(&addNode->value(), key);
2270 if (bucket.head() == NULL) {
2271 bucket.setHead(addNode);
2272 bucket.setTail(addNode);
2275 bucket.tail()->setNext(addNode);
2276 bucket.setTail(addNode);
2278 d_numElements.addRelaxed(1);
2279 bucket.incrementSize(1);
2285template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2287bsl::size_t StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::setValue(
2292 typedef StripedUnorderedContainerImpl_Bucket<KEY, VALUE> BucketClass;
2293 typename BucketClass::BucketScope setAll = scope == e_SCOPE_ALL
2294 ? BucketClass::e_BUCKETSCOPE_ALL
2295 : BucketClass::e_BUCKETSCOPE_FIRST;
2297 bsl::size_t bucketIdx;
2298 LEWGuard guard(lockWrite(&bucketIdx, key));
2300 StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket =
2301 d_buckets[bucketIdx];
2303 bsl::size_t count = bucket.setValue(key, d_comparator, value, setAll);
2306 d_numElements.addRelaxed(1);
2313template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2316StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::bucketIndex(
2318 bsl::size_t numBuckets)
const
2320 bsl::size_t hashVal = d_hasher(key);
2321 bsl::size_t bucketIdx =
2326template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2329StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::bucketToStripe(
2330 bsl::size_t bucketIndex)
const
2332 return bucketIndex & d_hashMask;
2335template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2336template <
class VECTOR>
2339StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::getValueImpl(
2341 const KEY& key)
const
2343 static const bool isVector =
2345#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
2355 bsl::size_t bucketIdx;
2356 LERGuard guard(lockRead(&bucketIdx, key));
2358 bsl::size_t count = 0;
2359 const StripedUnorderedContainerImpl_Bucket<KEY, VALUE>& bucket = d_buckets[
2362 StripedUnorderedContainerImpl_Node<KEY, VALUE> *curNode = bucket.head();
2363 for (; curNode != NULL; curNode = curNode->next()) {
2364 if (d_comparator(curNode->key(), key)) {
2365 valuesPtr->push_back(curNode->value());
2372template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2374StripedUnorderedContainerImpl_LockElement *
2375StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::lockRead(
2376 bsl::size_t *bucketIdx,
2377 const KEY& key)
const
2380 bsl::size_t hashVal = d_hasher(key);
2381 bsl::size_t numBuckets = d_numBuckets;
2382 bsl::size_t bucketIndex =
2384 bsl::size_t stripeIdx = bucketToStripe(bucketIndex);
2385 LockElement& lockElement = d_locks_p[stripeIdx];
2386 lockElement.lockR();
2388 if (numBuckets != d_numBuckets) {
2392 *bucketIdx = bucketIndex;
2393 return &lockElement;
2396template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2398StripedUnorderedContainerImpl_LockElement *
2399StripedUnorderedContainerImpl<KEY, VALUE, HASH, EQUAL>::lockWrite(
2400 bsl::size_t *bucketIdx,
2401 const KEY& key)
const
2404 bsl::size_t hashVal = d_hasher(key);
2405 bsl::size_t numBuckets = d_numBuckets;
2406 bsl::size_t bucketIndex =
2408 bsl::size_t stripeIdx = bucketToStripe(bucketIndex);
2409 LockElement& lockElement = d_locks_p[stripeIdx];
2410 lockElement.lockW();
2413 if (numBuckets != d_numBuckets) {
2417 *bucketIdx = bucketIndex;
2418 return &lockElement;
2422template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2426 bsl::size_t numInitialBuckets,
2427 bsl::size_t numStripes,
2429: d_numStripes(powerCeil(numStripes))
2430, d_numBuckets(adjustBuckets(numInitialBuckets, d_numStripes))
2431, d_hashMask(d_numStripes - 1)
2432, d_maxLoadFactor(1.0)
2437, d_buckets(d_numBuckets, basicAllocator)
2438, d_allocator_p(
bslma::Default::allocator(basicAllocator))
2440 d_state = k_REHASH_ENABLED;
2446 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2451template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2456 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2457 bslma::DestructionUtil::destroy(&d_locks_p[i]);
2459 d_allocator_p->deallocate(d_locks_p);
2463template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2468 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2469 d_locks_p[i].lockW();
2471 for (bsl::size_t j = 0; j < d_numBuckets; ++j) {
2472 d_buckets[j].clear();
2475 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2476 d_locks_p[i].unlockW();
2480template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2485 int oldState = d_state.load();
2486 int newState = oldState & ~k_REHASH_ENABLED;
2487 if (oldState == d_state.testAndSwap(oldState, newState)) {
2493template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2498 int oldState = d_state.load();
2499 int newState = oldState | k_REHASH_ENABLED;
2500 if (oldState == d_state.testAndSwap(oldState, newState)) {
2506template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2511 return erase(key, e_SCOPE_ALL);
2514template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2520 return eraseIf(key, e_SCOPE_ALL, predicate);
2523template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2524template <
class RANDOM_ITER>
2533 return eraseBulk(first, last, e_SCOPE_ALL);
2536template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2537template <
class RANDOM_ITER>
2546 return eraseBulk(first, last, e_SCOPE_FIRST);
2549template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2554 return erase(key, e_SCOPE_FIRST);
2557template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2564 return eraseIf(key, e_SCOPE_FIRST, predicate);
2567template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2573 insert(key, value, e_INSERT_ALWAYS);
2576template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2585template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2586template <
class RANDOM_ITER>
2594 insertBulk(first, last, e_INSERT_ALWAYS);
2597template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2598template <
class RANDOM_ITER>
2607 return insertBulk(first, last, e_INSERT_UNIQUE);
2610template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2617 return insert(key, value, e_INSERT_UNIQUE);
2620template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2630template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2633 float newMaxLoadFactor)
2637 d_maxLoadFactor = newMaxLoadFactor;
2641template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2643 bsl::size_t numBuckets)
2647 if (numBuckets < 2) {
2650 if (numBuckets < d_numStripes) {
2651 numBuckets = d_numStripes;
2653 numBuckets = powerCeil(numBuckets);
2655 if (numBuckets == d_numBuckets) {
2663 int oldState = d_state.testAndSwap(
2665 k_REHASH_ENABLED | k_REHASH_IN_PROGRESS);
2666 if (oldState != k_REHASH_ENABLED) {
2676 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2677 d_locks_p[i].lockW();
2682 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
2689 bucket.
head(); curNode != NULL;) {
2693 bsl::size_t newBucketIdx = bucketIndex(curNode->key(),
2695 curNode->setNext(NULL);
2696 newBuckets[newBucketIdx].addNode(curNode);
2705 d_buckets.swap(newBuckets);
2708 d_numBuckets = numBuckets;
2712 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2713 d_locks_p[i].unlockW();
2717 d_state = d_state & ~k_REHASH_IN_PROGRESS;
2720template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2727 return setComputedValue(key, visitor, e_SCOPE_ALL);
2730template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2737 return setComputedValue(key, visitor, e_SCOPE_FIRST);
2740template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2747 return setValue(key, value, e_SCOPE_ALL);
2750template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2757 return setValue(key, value, e_SCOPE_FIRST);
2760template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2767 bsl::size_t bucketIdx;
2768 LEWGuard guard(lockWrite(&bucketIdx, key));
2771 d_buckets[bucketIdx];
2773 bsl::size_t count = bucket.
setValue(key,
2778 d_numElements.addRelaxed(1);
2784template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2790 return visit(key, visitor);
2793template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2799 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
2800 d_locks_p[i].lockW();
2805 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
2810 bucket.
head(); curNode != NULL;
2811 curNode = curNode->next()) {
2813 bool ret = visitor(&(curNode->value()), curNode->key());
2815 d_locks_p[i].unlockW();
2820 d_locks_p[i].unlockW();
2825template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2831 bsl::size_t bucketIdx;
2832 LEWGuard guard(lockWrite(&bucketIdx, key));
2835 d_buckets[bucketIdx];
2840 for (; curNode != NULL; curNode = curNode->
next()) {
2841 if (d_comparator(curNode->
key(), key)) {
2843 bool ret = visitor(&curNode->
value(), key);
2853template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2858 return d_numBuckets;
2861template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2865 const KEY& key)
const
2867 return bucketIndex(key, d_numBuckets);
2870template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2873 bsl::size_t index)
const
2877 return d_buckets[index].size();
2880template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2884 return d_state == k_REHASH_ENABLED;
2887template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2891 for (bsl::size_t i = 0; i < d_numBuckets; ++i) {
2892 if (!d_buckets[i].empty()) {
2899template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2904 return d_comparator;
2907template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2911 const KEY& key)
const
2915 bsl::size_t bucketIdx;
2916 LERGuard guard(lockRead(&bucketIdx, key));
2922 for (; curNode != NULL; curNode = curNode->
next()) {
2923 if (d_comparator(curNode->
key(), key)) {
2924 *value = curNode->
value();
2931template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2935 const KEY& key)
const
2937 return getValueImpl(valuesPtr, key);
2940template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2943 std::vector<VALUE> *valuesPtr,
2944 const KEY& key)
const
2946 return getValueImpl(valuesPtr, key);
2949#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
2950template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2953 std::pmr::vector<VALUE> *valuesPtr,
2954 const KEY& key)
const
2956 return getValueImpl(valuesPtr, key);
2960template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2968template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2973 return d_state & k_REHASH_ENABLED;
2976template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2981 return static_cast<float>(d_numElements.loadRelaxed()) /
2982 static_cast<float>(d_numBuckets);
2985template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2990 return d_maxLoadFactor;
2993template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
2998 return static_cast<bsl::size_t
>(d_numStripes);
3001template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3007 for (bsl::size_t i = 0; i < d_numStripes; ++i) {
3008 d_locks_p[i].lockR();
3013 for (bsl::size_t j = i; j < d_numBuckets; j += d_numStripes) {
3018 bucket.
head(); curNode != NULL;
3019 curNode = curNode->next()) {
3021 bool ret = visitor(curNode->value(), curNode->key());
3023 d_locks_p[i].unlockR();
3028 d_locks_p[i].unlockR();
3033template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3039 bsl::size_t bucketIdx;
3040 LERGuard guard(lockRead(&bucketIdx, key));
3043 d_buckets[bucketIdx];
3048 for (; curNode != NULL; curNode = curNode->
next()) {
3049 if (d_comparator(curNode->
key(), key)) {
3051 bool ret = visitor(curNode->
value(), key);
3060template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3065 return d_numElements.loadRelaxed();
3070template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3075 return d_allocator_p;
3083template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3093template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3098 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3099 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3100 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3101 lockElement.
lockR();
3104template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3109 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3110 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3111 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3112 lockElement.
lockW();
3115template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3120 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3121 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3122 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3126template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
3131 bsl::size_t bucketIdx = d_hash.bucketIndex(key);
3132 bsl::size_t stripeIdx = d_hash.bucketToStripe(bucketIdx);
3133 LockElement& lockElement = d_hash.d_locks_p[stripeIdx];
3142 const StripedUnorderedContainerImpl_SortItem& rhs)
3144 if (lhs.d_stripeIdx < rhs.d_stripeIdx) {
3147 if (lhs.d_stripeIdx > rhs.d_stripeIdx) {
3150 if (lhs.d_dataIdx < rhs.d_dataIdx) {
3158template <
class KEY,
class VALUE,
class HASH,
class EQUAL>
Definition bdlcc_stripedunorderedcontainerimpl.h:304
void addNode(StripedUnorderedContainerImpl_Node< KEY, VALUE > *nodePtr)
Add the specified nodePtr node at the end of this bucket.
Definition bdlcc_stripedunorderedcontainerimpl.h:1580
StripedUnorderedContainerImpl_Node< KEY, VALUE > * tail() const
Return address of the tail (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:1765
void setSize(bsl::size_t value)
Set the size attribute of this bucket to the specified value.
Definition bdlcc_stripedunorderedcontainerimpl.h:1638
void setHead(StripedUnorderedContainerImpl_Node< KEY, VALUE > *value)
Definition bdlcc_stripedunorderedcontainerimpl.h:1630
BucketScope
Definition bdlcc_stripedunorderedcontainerimpl.h:338
@ e_BUCKETSCOPE_FIRST
Definition bdlcc_stripedunorderedcontainerimpl.h:340
@ e_BUCKETSCOPE_ALL
Definition bdlcc_stripedunorderedcontainerimpl.h:341
~StripedUnorderedContainerImpl_Bucket()
Destroy this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1572
void setTail(StripedUnorderedContainerImpl_Node< KEY, VALUE > *value)
Definition bdlcc_stripedunorderedcontainerimpl.h:1646
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:1757
StripedUnorderedContainerImpl_Node< KEY, VALUE > ** headAddress()
Return the address of the head (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:1615
void incrementSize(int amount)
Definition bdlcc_stripedunorderedcontainerimpl.h:1622
StripedUnorderedContainerImpl_Node< KEY, VALUE > * head() const
Return the head (node) of this bucket list.
Definition bdlcc_stripedunorderedcontainerimpl.h:1750
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:1774
bsl::size_t setValue(const KEY &key, const EQUAL &equal, const VALUE &value, BucketScope scope)
Definition bdlcc_stripedunorderedcontainerimpl.h:1654
bool empty() const
Definition bdlcc_stripedunorderedcontainerimpl.h:1742
void clear()
Empty StripedUnorderedContainerImpl_Bucket and delete all nodes.
Definition bdlcc_stripedunorderedcontainerimpl.h:1597
Definition bdlcc_stripedunorderedcontainerimpl.h:1315
StripedUnorderedContainerImpl_LockElementReadGuard(StripedUnorderedContainerImpl_LockElement *lockElementPtr)
Definition bdlcc_stripedunorderedcontainerimpl.h:1825
~StripedUnorderedContainerImpl_LockElementReadGuard()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1834
void release()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1840
Definition bdlcc_stripedunorderedcontainerimpl.h:1350
~StripedUnorderedContainerImpl_LockElementWriteGuard()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1864
StripedUnorderedContainerImpl_LockElementWriteGuard(StripedUnorderedContainerImpl_LockElement *lockElementPtr)
Definition bdlcc_stripedunorderedcontainerimpl.h:1855
void release()
Release the guarded object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1870
Definition bdlcc_stripedunorderedcontainerimpl.h:1259
void lockR()
Read lock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:1795
void unlockW()
Write unlock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:1813
void unlockR()
Read unlock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:1807
StripedUnorderedContainerImpl_LockElement()
Create an empty StripedUnorderedContainerImpl_LockElement object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1787
void lockW()
Write lock the lock element.
Definition bdlcc_stripedunorderedcontainerimpl.h:1801
Definition bdlcc_stripedunorderedcontainerimpl.h:206
~StripedUnorderedContainerImpl_Node()
Destroy this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1470
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:1530
const KEY & key() const
Return a const reference to the key attribute of this object.
Definition bdlcc_stripedunorderedcontainerimpl.h:1505
void setNext(StripedUnorderedContainerImpl_Node *nextPtr)
Set this node's pointer-to-next-node to the specified nextPtr.
Definition bdlcc_stripedunorderedcontainerimpl.h:1489
StripedUnorderedContainerImpl_Node ** nextAddress()
Return the address of the pointer to the next node.
Definition bdlcc_stripedunorderedcontainerimpl.h:1482
StripedUnorderedContainerImpl_Node * next() const
Return the pointer to the next node.
Definition bdlcc_stripedunorderedcontainerimpl.h:1513
VALUE & value()
Definition bdlcc_stripedunorderedcontainerimpl.h:1497
Definition bdlcc_stripedunorderedcontainerimpl.h:1211
void unlockRead(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3118
void lockWrite(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3107
void lockRead(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3095
void unlockWrite(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:3129
~StripedUnorderedContainerImpl_TestUtil()=default
StripedUnorderedContainerImpl_TestUtil(StripedUnorderedContainerImpl< KEY, VALUE, HASH, EQUAL > &hash)
Definition bdlcc_stripedunorderedcontainerimpl.h:3086
Definition bdlcc_stripedunorderedcontainerimpl.h:473
bsl::size_t getValue(VALUE *value, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:2909
bsl::size_t bucketSize(bsl::size_t index) const
Definition bdlcc_stripedunorderedcontainerimpl.h:2872
bool empty() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2889
StripedUnorderedContainerImpl_Node< KEY, VALUE > Node
Node in a bucket.
Definition bdlcc_stripedunorderedcontainerimpl.h:483
float loadFactor() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2979
bsl::size_t setValueFirst(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2763
int update(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2786
int visitReadOnly(const KEY &key, const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3035
float maxLoadFactor() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2988
bsl::size_t insertUnique(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2623
bsl::size_t setValueFirst(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2753
bsl::size_t numStripes() const
Return the number of stripes in the hash.
Definition bdlcc_stripedunorderedcontainerimpl.h:2996
HASH hashFunction() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2963
bsl::function< bool(VALUE *, const KEY &)> VisitorFunction
Definition bdlcc_stripedunorderedcontainerimpl.h:497
bsl::size_t bucketIndex(const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:2864
bsl::size_t insertBulkUnique(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2601
void rehash(bsl::size_t numBuckets)
Definition bdlcc_stripedunorderedcontainerimpl.h:2642
bsl::size_t insertUnique(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2613
bsl::pair< KEY, VALUE > KVType
Value type of a bulk insert entry.
Definition bdlcc_stripedunorderedcontainerimpl.h:486
int visit(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2827
void disableRehash()
Prevent rehash until the enableRehash method is called.
Definition bdlcc_stripedunorderedcontainerimpl.h:2482
bool isRehashEnabled() const
Return true if rehash is enabled, or false otherwise.
Definition bdlcc_stripedunorderedcontainerimpl.h:2971
bsl::size_t eraseFirstIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedcontainerimpl.h:2560
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:2425
void clear()
Definition bdlcc_stripedunorderedcontainerimpl.h:2465
void insertBulkAlways(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2588
bsl::size_t size() const
Return the current number of elements in this hash.
Definition bdlcc_stripedunorderedcontainerimpl.h:3063
bsl::size_t eraseFirst(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:2551
bsl::size_t eraseBulkFirst(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2540
void insertAlways(const KEY &key, bslmf::MovableRef< VALUE > value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2578
~StripedUnorderedContainerImpl()
Destroy this hash map. This method is not thread-safe.
Definition bdlcc_stripedunorderedcontainerimpl.h:2454
bsl::size_t setValueAll(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2743
void insertAlways(const KEY &key, const VALUE &value)
Definition bdlcc_stripedunorderedcontainerimpl.h:2569
bslma::Allocator * allocator() const
Definition bdlcc_stripedunorderedcontainerimpl.h:3073
void maxLoadFactor(float newMaxLoadFactor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2632
int visitReadOnly(const ReadOnlyVisitorFunction &visitor) const
Definition bdlcc_stripedunorderedcontainerimpl.h:3002
int setComputedValueAll(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2723
bsl::function< bool(const VALUE &)> EraseIfValuePredicate
Definition bdlcc_stripedunorderedcontainerimpl.h:519
void enableRehash()
Definition bdlcc_stripedunorderedcontainerimpl.h:2495
bool canRehash() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2882
bsl::size_t eraseAllIf(const KEY &key, const EraseIfValuePredicate &predicate)
Definition bdlcc_stripedunorderedcontainerimpl.h:2516
friend class StripedUnorderedContainerImpl_LockElement
Definition bdlcc_stripedunorderedcontainerimpl.h:614
bsl::size_t eraseBulkAll(RANDOM_ITER first, RANDOM_ITER last)
Definition bdlcc_stripedunorderedcontainerimpl.h:2527
int setComputedValueFirst(const KEY &key, const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2733
bsl::function< bool(const VALUE &, const KEY &)> ReadOnlyVisitorFunction
Definition bdlcc_stripedunorderedcontainerimpl.h:510
bsl::size_t bucketCount() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2856
bsl::size_t getValue(std::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:2942
@ k_DEFAULT_NUM_STRIPES
Definition bdlcc_stripedunorderedcontainerimpl.h:479
@ k_DEFAULT_NUM_BUCKETS
Definition bdlcc_stripedunorderedcontainerimpl.h:478
EQUAL equalFunction() const
Definition bdlcc_stripedunorderedcontainerimpl.h:2902
bsl::size_t getValue(bsl::vector< VALUE > *valuesPtr, const KEY &key) const
Definition bdlcc_stripedunorderedcontainerimpl.h:2933
int visit(const VisitorFunction &visitor)
Definition bdlcc_stripedunorderedcontainerimpl.h:2794
bsl::size_t eraseAll(const KEY &key)
Definition bdlcc_stripedunorderedcontainerimpl.h:2508
Forward declaration.
Definition bslstl_function.h:934
Definition bslstl_pair.h:1210
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
virtual void * allocate(size_type size)=0
Definition bslma_destructorproctor.h:259
void release()
Definition bslma_destructorproctor.h:325
Definition bslma_rawdeleterproctor.h:242
Definition bslmf_movableref.h:751
Definition bslmt_readerwritermutex.h:244
void unlockRead()
Definition bslmt_readerwritermutex.h:373
void unlockWrite()
Definition bslmt_readerwritermutex.h:379
void lockRead()
Definition bslmt_readerwritermutex.h:343
void lockWrite()
Definition bslmt_readerwritermutex.h:349
Definition bsls_atomic.h:743
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlcc_boundedqueue.h:270
bool operator<(const StripedUnorderedContainerImpl_SortItem &lhs, const StripedUnorderedContainerImpl_SortItem &rhs)
Definition balxml_encoderoptions.h:68
Definition bdlcc_stripedunorderedcontainerimpl.h:1379
int d_stripeIdx
Definition bdlcc_stripedunorderedcontainerimpl.h:1382
int d_dataIdx
Definition bdlcc_stripedunorderedcontainerimpl.h:1383
bsl::size_t d_hashVal
Definition bdlcc_stripedunorderedcontainerimpl.h:1384
Definition bslstl_equalto.h:311
Definition bslstl_hash.h:498
Definition bslmf_issame.h:146
static std::size_t computeBucketIndex(std::size_t hashCode, std::size_t numBuckets)
Definition bslalg_hashtableimputil.h:845
static void moveConstruct(TARGET_TYPE *address, TARGET_TYPE &original, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1642
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static Allocator * defaultAllocator()
Definition bslma_default.h:889
Definition bslma_usesbslmaallocator.h:343
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
Definition bsls_objectbuffer.h:276
TYPE * address()
Definition bsls_objectbuffer.h:334
TYPE & object()
Definition bsls_objectbuffer.h:351