8#ifndef INCLUDED_BDLC_FLATHASHTABLE
9#define INCLUDED_BDLC_FLATHASHTABLE
167#include <bdlscm_version.h>
200#include <bsl_cstddef.h>
201#include <bsl_cstdint.h>
202#include <bsl_cstring.h>
203#include <bsl_iterator.h>
204#include <bsl_limits.h>
205#include <bsl_type_traits.h>
206#include <bsl_utility.h>
208#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
212# define COMPILING_BDLC_FLATHASHTABLE_H
214# undef COMPILING_BDLC_FLATHASHTABLE_H
221struct FlatHashTable_ImplUtil;
223template <
class ENTRY>
224class FlatHashTable_IteratorImp;
226template <
class ENTRY>
238template <
class ENTRY>
246 const bsl::uint8_t *d_controls_p;
247 bsl::size_t d_additionalLength;
267 const bsl::uint8_t *controls,
268 bsl::size_t additionalLength);
305template <
class ENTRY>
315template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
339 bsl::uint8_t *d_controls_p;
341 bsl::size_t d_capacity;
342 int d_groupControlShift;
354 static bsl::size_t findAvailable(bsl::uint8_t *
controls,
370 bsl::size_t indexOfKey(
bool *notFound,
372 bsl::size_t hashValue);
379 void rehashRaw(bsl::size_t newCapacity);
387 bsl::size_t findKey(
const KEY& key, bsl::size_t hashValue)
const;
391 bsl::size_t minimumCompliantCapacity(bsl::size_t minimumCapacity)
const;
487 template <
class KEY_TYPE>
505#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
512 template<
class... ARGS>
546#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
547 template <
class ENTRY_TYPE>
561 template <
class ENTRY_TYPE>
571 bsl::size_t hashValue = d_hasher(ENTRY_UTIL::key(entry));
572 bsl::size_t index = indexOfKey(¬Found,
573 ENTRY_UTIL::key(entry),
577 ENTRY_UTIL::construct(
582 d_controls_p[index] =
static_cast<bsl::uint8_t
>(
589 d_controls_p + index,
590 d_capacity - index - 1),
604 template <
class INPUT_ITERATOR>
605 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
614 void rehash(bsl::size_t minimumCapacity);
633#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
643 template<
class... ARGS>
655 template <
class... ARGS>
657 BloombergLP::bslmf::MovableRef<KEY> key,
700 bsl::size_t
count(
const KEY& key)
const;
722 const KEY& key)
const;
782template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
792template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
801template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
823 template <
class ENTRY_TYPE>
824 class DestroyEntryArrayProctor;
858 template <
class ENTRY_TYPE>
859 static void copyEntryAndControlArrays(
860 ENTRY_TYPE *firstDestinationEntry,
861 bsl::uint8_t *firstDestinationControl,
862 const ENTRY_TYPE *firstSourceEntry,
863 const ENTRY_TYPE *lastSourceEntry,
864 const bsl::uint8_t *firstSourceControl,
865 const bsl::uint8_t *lastSourceControl,
868 template <
class ENTRY_TYPE>
869 static void copyEntryAndControlArrays(
870 ENTRY_TYPE *firstDestinationEntry,
871 bsl::uint8_t *firstDestinationControl,
872 const ENTRY_TYPE *firstSourceEntry,
873 const ENTRY_TYPE *lastSourceEntry,
874 const bsl::uint8_t *firstSourceControl,
875 const bsl::uint8_t *lastSourceControl,
896 template <
class ENTRY_TYPE>
897 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
898 ENTRY_TYPE *lastEntry,
899 const bsl::uint8_t *firstControl,
900 const bsl::uint8_t *lastControl,
902 template <
class ENTRY_TYPE>
903 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
904 ENTRY_TYPE *lastEntry,
905 const bsl::uint8_t *firstControl,
906 const bsl::uint8_t *lastControl,
939 template <
class ENTRY_TYPE>
941 copyEntryAndControlArrays(ENTRY_TYPE *firstDestinationEntry,
942 bsl::uint8_t *firstDestinationControl,
943 const ENTRY_TYPE *firstSourceEntry,
944 const ENTRY_TYPE *lastSourceEntry,
945 const bsl::uint8_t *firstSourceControl,
946 const bsl::uint8_t *lastSourceControl,
963 template <
class ENTRY_TYPE>
964 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
965 ENTRY_TYPE *lastEntry,
966 const bsl::uint8_t *firstControl,
967 const bsl::uint8_t *lastControl);
979template <
class ENTRY_TYPE>
980class FlatHashTable_ImplUtil::DestroyEntryArrayProctor {
989 ENTRY_TYPE *d_firstEntry_p;
992 ENTRY_TYPE *d_lastEntry_p;
995 const bsl::uint8_t *d_firstControl_p;
998 const bsl::uint8_t *d_lastControl_p;
1001 DestroyEntryArrayProctor(
const DestroyEntryArrayProctor&);
1002 DestroyEntryArrayProctor& operator=(
const DestroyEntryArrayProctor&);
1015 DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
1016 ENTRY_TYPE *lastEntry,
1017 const bsl::uint8_t *firstControl,
1018 const bsl::uint8_t *lastControl);
1023 ~DestroyEntryArrayProctor();
1029 void moveEnd(bsl::ptrdiff_t offset);
1048template <
class ENTRY>
1053, d_additionalLength(0)
1057template <
class ENTRY>
1061 const bsl::uint8_t *controls,
1062 bsl::size_t additionalLength)
1063: d_entries_p(entries)
1064, d_controls_p(controls)
1065, d_additionalLength(additionalLength)
1069template <
class ENTRY>
1073: d_entries_p(original.d_entries_p)
1074, d_controls_p(original.d_controls_p)
1075, d_additionalLength(original.d_additionalLength)
1080template <
class ENTRY>
1085 d_entries_p = rhs.d_entries_p;
1086 d_controls_p = rhs.d_controls_p;
1087 d_additionalLength = rhs.d_additionalLength;
1092template <
class ENTRY>
1099 while (d_additionalLength) {
1102 --d_additionalLength;
1103 if (0 == (*d_controls_p & 0x80)) {
1113template <
class ENTRY>
1120 return *d_entries_p;
1126template <
class ENTRY>
1129 const FlatHashTable_IteratorImp<ENTRY>& b)
1131 return a.d_entries_p == b.d_entries_p
1132 && a.d_controls_p == b.d_controls_p
1133 && a.d_additionalLength == b.d_additionalLength;
1143template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1144bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findAvailable(
1145 bsl::uint8_t *controls,
1147 bsl::size_t capacity)
1151 for (bsl::size_t i = 0; i < capacity; i += GroupControl::k_SIZE) {
1152 bsl::uint8_t *controlStart = controls + index;
1154 GroupControl groupControl(controlStart);
1155 bsl::uint32_t candidates = groupControl.available();
1162 index = (index + GroupControl::k_SIZE) & (capacity - 1);
1165 BSLS_ASSERT_OPT(
false &&
"execution should never reach this location");
1170template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1171bsl::size_t FlatHashTable<KEY,
1175 EQUAL>::indexOfKey(
bool *notFound,
1177 bsl::size_t hashValue)
1181 bsl::size_t index = findKey(key, hashValue);
1183 if (index == d_capacity) {
1186 if (d_size >= k_MAX_LOAD_FACTOR_NUMERATOR
1187 * (d_capacity / k_MAX_LOAD_FACTOR_DENOMINATOR)) {
1188 rehashRaw(d_capacity > 0 ? 2 * d_capacity : k_MIN_CAPACITY);
1191 index = (hashValue >> d_groupControlShift) * GroupControl::k_SIZE;
1192 index = findAvailable(d_controls_p, index, d_capacity);
1201template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1202void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::rehashRaw(
1203 bsl::size_t newCapacity)
1208 FlatHashTable tmp(newCapacity,
1213 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
1214 bsl::uint8_t *controlStart = d_controls_p + i;
1215 ENTRY *entryStart = d_entries_p + i;
1217 GroupControl groupControl(controlStart);
1218 bsl::uint32_t candidates = groupControl.inUse();
1219 while (candidates) {
1221 ENTRY *entry = entryStart + offset;
1227 *(controlStart + offset) = GroupControl::k_ERASED;
1231 bsl::size_t hashValue = tmp.d_hasher(ENTRY_UTIL::key(*entry));
1232 bsl::size_t index = (hashValue >> tmp.d_groupControlShift)
1233 * GroupControl::k_SIZE;
1235 index = findAvailable(tmp.d_controls_p, index, tmp.d_capacity);
1244 tmp.d_controls_p[index] =
static_cast<bsl::uint8_t
>(
1245 hashValue & k_HASHLET_MASK);
1259 d_groupControlShift = 0;
1269template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1270bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findKey(
1272 bsl::size_t hashValue)
const
1276 bsl::size_t index = (hashValue >> d_groupControlShift)
1277 * GroupControl::k_SIZE;
1278 bsl::uint8_t hashlet =
static_cast<bsl::uint8_t
>(
1279 hashValue & k_HASHLET_MASK);
1281 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
1282 bsl::uint8_t *controlStart = d_controls_p + index;
1283 ENTRY *entryStart = d_entries_p + index;
1285 GroupControl groupControl(controlStart);
1286 bsl::uint32_t candidates = groupControl.match(hashlet);
1287 while (candidates) {
1290 ENTRY *entry = entryStart + offset;
1293 d_equal(ENTRY_UTIL::key(*entry), key))) {
1294 return index + offset;
1302 index = (index + GroupControl::k_SIZE) & (d_capacity - 1);
1308template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1309bsl::size_t FlatHashTable<KEY,
1313 EQUAL>::minimumCompliantCapacity(
1314 bsl::size_t minimumCapacity)
const
1316 bsl::size_t minForEntries = ((d_size + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
1317 / k_MAX_LOAD_FACTOR_NUMERATOR)
1318 * k_MAX_LOAD_FACTOR_DENOMINATOR;
1320 bsl::size_t capacity = minimumCapacity >= minForEntries
1325 capacity = capacity > k_MIN_CAPACITY
1327 static_cast<bsl::uint64_t
>(capacity)))
1335template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1338 bsl::size_t capacity,
1346, d_groupControlShift(0)
1349, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1354 static_cast<bsl::uint64_t
>(
capacity)))
1357 d_groupControlShift =
static_cast<int>(
1358 sizeof(bsl::size_t) * 8
1363 ENTRY *
entries =
static_cast<ENTRY *
>(
1364 d_allocator_p->
allocate(d_capacity *
sizeof(ENTRY)));
1369 d_controls_p =
static_cast<bsl::uint8_t *
>(
1370 d_allocator_p->
allocate(d_capacity));
1378template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1387, d_groupControlShift(0)
1388, d_hasher(original.hash_function())
1389, d_equal(original.key_eq())
1390, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1392 if (0 != original.d_capacity) {
1393 bsl::uint8_t *
const controls =
static_cast<bsl::uint8_t *
>(
1394 d_allocator_p->
allocate(original.d_capacity));
1399 ENTRY *
const entries =
static_cast<ENTRY *
>(
1400 d_allocator_p->
allocate(original.d_capacity *
sizeof(ENTRY)));
1405 ImplUtil::copyEntryAndControlArrays(
1408 original.d_entries_p,
1409 original.d_entries_p + original.d_capacity,
1410 original.d_controls_p,
1411 original.d_controls_p + original.d_capacity,
1419 d_size = original.d_size;
1420 d_capacity = original.d_capacity;
1421 d_groupControlShift = original.d_groupControlShift;
1425template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1429: d_entries_p(
bslmf::MovableRefUtil::access(original).d_entries_p)
1430, d_controls_p(
bslmf::MovableRefUtil::access(original).d_controls_p)
1431, d_size(
bslmf::MovableRefUtil::access(original).d_size)
1432, d_capacity(
bslmf::MovableRefUtil::access(original).d_capacity)
1433, d_groupControlShift(
1434 bslmf::MovableRefUtil::access(original).d_groupControlShift)
1435, d_hasher(
bslmf::MovableRefUtil::access(original).d_hasher)
1436, d_equal(
bslmf::MovableRefUtil::access(original).d_equal)
1437, d_allocator_p(
bslmf::MovableRefUtil::access(original).d_allocator_p)
1441 reference.d_entries_p = 0;
1442 reference.d_controls_p = 0;
1443 reference.d_size = 0;
1444 reference.d_capacity = 0;
1445 reference.d_groupControlShift = 0;
1448template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1456, d_groupControlShift(0)
1457, d_hasher(
bslmf::MovableRefUtil::access(original).d_hasher)
1458, d_equal(
bslmf::MovableRefUtil::access(original).d_equal)
1459, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1462 if (d_allocator_p == reference.d_allocator_p) {
1468 &reference.d_groupControlShift);
1470 else if (reference.d_capacity) {
1471 bsl::uint8_t *
const controls =
static_cast<bsl::uint8_t *
>(
1472 d_allocator_p->
allocate(reference.d_capacity));
1477 ENTRY *
const entries =
static_cast<ENTRY *
>(
1478 d_allocator_p->
allocate(reference.d_capacity *
sizeof(ENTRY)));
1483 ImplUtil::copyEntryAndControlArrays(
1486 reference.d_entries_p,
1487 reference.d_entries_p + reference.d_capacity,
1488 reference.d_controls_p,
1489 reference.d_controls_p + reference.d_capacity,
1497 d_size = reference.d_size;
1498 d_capacity = reference.d_capacity;
1499 d_groupControlShift = reference.d_groupControlShift;
1503template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1508 (d_capacity == 0 && d_groupControlShift == 0) ||
1509 (d_groupControlShift ==
1510 static_cast<int>(
sizeof(bsl::size_t) * 8 -
1512 d_capacity / GroupControl::k_SIZE)))));
1514 if (0 != d_entries_p) {
1515 ImplUtil::destroyEntryArray(d_entries_p,
1516 d_entries_p + d_capacity,
1518 d_controls_p + d_capacity);
1526template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1539template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1546 if (
this != &reference) {
1554template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1555template <
class KEY_TYPE>
1561 bsl::size_t hashValue = d_hasher(key);
1562 bsl::size_t index = indexOfKey(¬Found, key, hashValue);
1565 ENTRY_UTIL::constructFromKey(d_entries_p + index,
1569 d_controls_p[index] =
static_cast<bsl::uint8_t
>(
1570 hashValue & k_HASHLET_MASK);
1575 return d_entries_p[index];
1578template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1582 ImplUtil::destroyEntryArray(d_entries_p,
1583 d_entries_p + d_capacity,
1585 d_controls_p + d_capacity);
1588 bsl::memset(d_controls_p, GroupControl::k_EMPTY, d_capacity);
1594template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1603 return bsl::make_pair(it1, it1);
1607 return bsl::make_pair(it1, it2);
1610#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1611template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1612template<
class... ARGS>
1620 ENTRY_UTIL::construct(value.
address(),
1630template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1643template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1651 EQUAL>::const_iterator position)
1655 bsl::size_t index = &*position - d_entries_p;
1656 bslma::DestructionUtil::destroy(d_entries_p + index);
1657 d_controls_p[index] = GroupControl::k_ERASED;
1661 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
1662 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
1663 return iterator(IteratorImp(d_entries_p + i,
1665 d_capacity - i - 1));
1672template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1676 typename FlatHashTable<KEY,
1680 EQUAL>::iterator position)
1687 bsl::size_t index = &*position - d_entries_p;
1688 bslma::DestructionUtil::destroy(d_entries_p + index);
1689 d_controls_p[index] = GroupControl::k_ERASED;
1693 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
1694 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
1695 return iterator(IteratorImp(d_entries_p + i,
1697 d_capacity - i - 1));
1704template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1707 typename FlatHashTable<KEY,
1711 EQUAL>::const_iterator first,
1712 typename FlatHashTable<KEY,
1716 EQUAL>::const_iterator last)
1720 if (last !=
end()) {
1721 bsl::size_t index = &*last - d_entries_p;
1722 rv = iterator(IteratorImp(d_entries_p + index,
1723 d_controls_p + index,
1724 d_capacity - index - 1));
1731 for (; first != last; ++first) {
1738template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1743 bsl::size_t index = findKey(key, d_hasher(key));
1744 if (index < d_capacity) {
1746 d_controls_p + index,
1747 d_capacity - index - 1));
1752template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1753template <
class INPUT_ITERATOR>
1756 INPUT_ITERATOR first,
1757 INPUT_ITERATOR last)
1759 for (; first != last; ++first) {
1764template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1767 bsl::size_t minimumCapacity)
1769 minimumCapacity = minimumCompliantCapacity(minimumCapacity);
1771 if (0 < minimumCapacity) {
1772 rehashRaw(minimumCapacity);
1781 d_groupControlShift = 0;
1785template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1788 bsl::size_t numEntries)
1790 if (0 == d_capacity && 0 == numEntries) {
1797 bsl::size_t minForEntries = ((numEntries + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
1798 / k_MAX_LOAD_FACTOR_NUMERATOR)
1799 * k_MAX_LOAD_FACTOR_DENOMINATOR;
1801 rehash(minForEntries);
1804template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1808 if (0 != d_entries_p) {
1809 ImplUtil::destroyEntryArray(d_entries_p,
1810 d_entries_p + d_capacity,
1812 d_controls_p + d_capacity);
1821 d_groupControlShift = 0;
1825#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1827template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1828template<
class... ARGS>
1837 bsl::size_t hashValue = d_hasher(key);
1838 bsl::size_t index = indexOfKey(¬Found, key, hashValue);
1841 ENTRY_UTIL::construct(d_entries_p + index,
1845 d_controls_p[index] =
static_cast<bsl::uint8_t
>(
1846 hashValue & k_HASHLET_MASK);
1851 d_controls_p + index,
1852 d_capacity - index - 1),
1857template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1858template<
class... ARGS>
1863 BloombergLP::bslmf::MovableRef<KEY> key,
1868 bsl::size_t hashValue = d_hasher(k);
1869 bsl::size_t index = indexOfKey(¬Found, k, hashValue);
1872 ENTRY_UTIL::construct(d_entries_p + index,
1876 d_controls_p[index] =
static_cast<bsl::uint8_t
>(
1877 hashValue & k_HASHLET_MASK);
1881 d_controls_p + index,
1882 d_capacity - index - 1),
1889template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1895 for (bsl::size_t i = 0; i < d_capacity; ++i) {
1896 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
1899 d_capacity - i - 1));
1906template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1916template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1933template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1941template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1944 const KEY& key)
const
1946 return find(key) != end();
1949template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1955 EQUAL>::controls()
const
1957 return d_controls_p;
1960template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1963 const KEY& key)
const
1965 return contains(key) ? 1 : 0;
1968template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1975template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1981 EQUAL>::entries()
const
1986template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
1992 EQUAL>::const_iterator,
1997 EQUAL>::const_iterator>
1999 const KEY& key)
const
2003 if (cit1 != end()) {
2006 return bsl::make_pair(cit1, cit2);
2009template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2014 bsl::size_t index = findKey(key, d_hasher(key));
2015 if (index < d_capacity) {
2017 d_controls_p + index,
2018 d_capacity - index - 1));
2023template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2030template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2037template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2043 EQUAL>::load_factor()
const
2045 return d_capacity > 0
2046 ?
static_cast<float>(d_size) /
static_cast<float>(d_capacity)
2050template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2056 EQUAL>::max_load_factor()
const
2058 return static_cast<float>(k_MAX_LOAD_FACTOR_NUMERATOR)
2059 /
static_cast<float>(k_MAX_LOAD_FACTOR_DENOMINATOR);
2062template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2071template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2077 for (bsl::size_t i = 0; i < d_capacity; ++i) {
2078 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
2082 d_capacity - i - 1));
2089template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2097template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2105template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2115template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2120 return d_allocator_p;
2126template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2132 const FlatHashTable<KEY,
2138 typedef typename FlatHashTable<KEY,
2142 EQUAL>::const_iterator ConstIterator;
2144 if (lhs.size() == rhs.size()) {
2145 ConstIterator lhsEnd = lhs.end();
2146 ConstIterator rhsEnd = rhs.end();
2148 if (lhs.capacity() <= rhs.capacity()) {
2149 for (ConstIterator it = lhs.begin(); it != lhsEnd; ++it) {
2150 ConstIterator i = rhs.find(ENTRY_UTIL::key(*it));
2151 if (i == rhsEnd || *i != *it) {
2158 for (ConstIterator it = rhs.begin(); it != rhsEnd; ++it) {
2159 ConstIterator i = lhs.find(ENTRY_UTIL::key(*it));
2160 if (i == lhsEnd || *i != *it) {
2170template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2176 const FlatHashTable<KEY,
2182 return !(lhs == rhs);
2186template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2188void bdlc::swap(FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& a,
2189 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& b)
2191 if (a.allocator() == b.allocator()) {
2197 typedef FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL> Table;
2199 Table futureA(b, a.allocator());
2200 Table futureB(a, b.allocator());
2208template <
class KEY,
class ENTRY,
class ENTRY_UTIL,
class HASH,
class EQUAL>
2225template <
class ENTRY_TYPE>
2227void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
2228 ENTRY_TYPE *firstDestinationEntry,
2229 bsl::uint8_t *firstDestinationControl,
2230 const ENTRY_TYPE *firstSourceEntry,
2231 const ENTRY_TYPE *lastSourceEntry,
2232 const bsl::uint8_t *firstSourceControl,
2233 const bsl::uint8_t *lastSourceControl,
2237 (void) isBitwiseCopyable;
2241 bsl::memcpy(firstDestinationControl,
2243 bsl::distance(firstSourceControl, lastSourceControl) *
2244 sizeof(bsl::uint8_t));
2246 const bsl::size_t numEntries =
static_cast<bsl::size_t
>(
2247 bsl::distance(firstSourceEntry, lastSourceEntry));
2249 DestroyEntryArrayProctor<ENTRY_TYPE> destroyEntriesProctor(
2250 firstDestinationEntry,
2251 firstDestinationEntry,
2252 firstDestinationControl,
2253 firstDestinationControl);
2255 for (bsl::size_t idx = 0; idx != numEntries; ++idx) {
2256 ENTRY_TYPE& destinationEntry = *(firstDestinationEntry + idx);
2257 const bsl::uint8_t& sourceControl = *(firstSourceControl + idx);
2258 const ENTRY_TYPE& sourceEntry = *(firstSourceEntry + idx);
2262 &destinationEntry, entryAllocator, sourceEntry);
2265 destroyEntriesProctor.moveEnd(1);
2268 destroyEntriesProctor.release();
2271template <
class ENTRY_TYPE>
2273void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
2274 ENTRY_TYPE *firstDestinationEntry,
2275 bsl::uint8_t *firstDestinationControl,
2276 const ENTRY_TYPE *firstSourceEntry,
2277 const ENTRY_TYPE *lastSourceEntry,
2278 const bsl::uint8_t *firstSourceControl,
2279 const bsl::uint8_t *lastSourceControl,
2283 (void) isBitwiseCopyable;
2287 bsl::memcpy(firstDestinationControl,
2289 bsl::distance(firstSourceControl, lastSourceControl) *
2290 sizeof(bsl::uint8_t));
2292#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
2293#pragma GCC diagnostic push
2294#pragma GCC diagnostic ignored "-Wclass-memaccess"
2297 bsl::memcpy(firstDestinationEntry,
2299 bsl::distance(firstSourceEntry, lastSourceEntry) *
2300 sizeof(ENTRY_TYPE));
2302#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
2303#pragma GCC diagnostic pop
2307template <
class ENTRY_TYPE>
2309void FlatHashTable_ImplUtil::destroyEntryArray(
2310 ENTRY_TYPE *firstEntry,
2311 ENTRY_TYPE *lastEntry,
2312 const bsl::uint8_t *firstControl,
2313 const bsl::uint8_t *lastControl,
2316 (void) triviallyDestructible;
2336 static_cast<void>(lastControl);
2338 const bsl::size_t numEntries =
2339 static_cast<bsl::size_t
>(bsl::distance(firstEntry, lastEntry));
2340 const bsl::size_t numGroupedEntries =
2343 for (bsl::size_t idx = 0;
2344 idx != numGroupedEntries;
2346 GroupControl groupControl(firstControl + idx);
2347 bsl::uint32_t candidates = groupControl.inUse();
2348 while (candidates) {
2350 bslma::DestructionUtil::destroy(firstEntry + idx + offset);
2355 for (bsl::size_t idx = numGroupedEntries; idx != numEntries; ++idx) {
2356 ENTRY_TYPE& entry = *(firstEntry + idx);
2357 const bsl::uint8_t& control = *(firstControl + idx);
2360 bslma::DestructionUtil::destroy(&entry);
2365template <
class ENTRY_TYPE>
2367void FlatHashTable_ImplUtil::destroyEntryArray(
2370 const bsl::uint8_t *,
2371 const bsl::uint8_t *,
2374 (void) triviallyDestructible;
2380template <
class ENTRY_TYPE>
2382void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
2383 ENTRY_TYPE *firstDestinationEntry,
2384 bsl::uint8_t *firstDestinationControl,
2385 const ENTRY_TYPE *firstSourceEntry,
2386 const ENTRY_TYPE *lastSourceEntry,
2387 const bsl::uint8_t *firstSourceControl,
2388 const bsl::uint8_t *lastSourceControl,
2392 bsl::distance(firstSourceControl, lastSourceControl));
2394 FlatHashTable_ImplUtil::copyEntryAndControlArrays(
2395 firstDestinationEntry,
2396 firstDestinationControl,
2405template <
class ENTRY_TYPE>
2407void FlatHashTable_ImplUtil::destroyEntryArray(
2408 ENTRY_TYPE *firstEntry,
2409 ENTRY_TYPE *lastEntry,
2410 const bsl::uint8_t *firstControl,
2411 const bsl::uint8_t *lastControl)
2414 bsl::distance(firstControl, lastControl));
2427 IsEntryTypeTriviallyDestructible;
2429 FlatHashTable_ImplUtil::destroyEntryArray(
2434 IsEntryTypeTriviallyDestructible());
2442template <
class ENTRY_TYPE>
2444FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
2445 ENTRY_TYPE>::DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
2446 ENTRY_TYPE *lastEntry,
2447 const bsl::uint8_t *firstControl,
2448 const bsl::uint8_t *lastControl)
2449: d_firstEntry_p(firstEntry)
2450, d_lastEntry_p(lastEntry)
2451, d_firstControl_p(firstControl)
2452, d_lastControl_p(lastControl)
2456template <
class ENTRY_TYPE>
2458FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
2459 ENTRY_TYPE>::~DestroyEntryArrayProctor()
2461 ImplUtil::destroyEntryArray(d_firstEntry_p,
2468template <
class ENTRY_TYPE>
2470void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::moveEnd(
2471 bsl::ptrdiff_t offset)
2473 d_lastEntry_p += offset;
2474 d_lastControl_p += offset;
2477template <
class ENTRY_TYPE>
2479void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::release()
2483 d_firstControl_p = 0;
2484 d_lastControl_p = 0;
Definition bdlc_flathashtable_groupcontrol.h:91
static const bsl::uint8_t k_EMPTY
Definition bdlc_flathashtable_groupcontrol.h:124
static const bsl::size_t k_SIZE
Definition bdlc_flathashtable_groupcontrol.h:126
Definition bdlc_flathashtable.h:240
FlatHashTable_IteratorImp & operator=(const FlatHashTable_IteratorImp &rhs)
Definition bdlc_flathashtable.h:1082
~FlatHashTable_IteratorImp()=default
FlatHashTable_IteratorImp()
Definition bdlc_flathashtable.h:1050
void operator++()
Definition bdlc_flathashtable.h:1094
ENTRY & operator*() const
Definition bdlc_flathashtable.h:1115
Definition bdlc_flathashtable.h:317
void clear()
Definition bdlc_flathashtable.h:1580
bsl::size_t erase(const KEY &key)
Definition bdlc_flathashtable.h:1632
iterator erase(const_iterator first, const_iterator last)
const ENTRY * entries() const
Definition bdlc_flathashtable.h:1981
static const bsl::size_t k_MIN_CAPACITY
Definition bdlc_flathashtable.h:398
bsl::pair< iterator, bool > try_emplace(BloombergLP::bslmf::MovableRef< KEY > key, ARGS &&... args)
float max_load_factor() const
Definition bdlc_flathashtable.h:2056
const_iterator cbegin() const
Definition bdlc_flathashtable.h:2092
iterator erase(const_iterator position)
void swap(FlatHashTable &other)
Definition bdlc_flathashtable.h:1918
FlatHashTable(bsl::size_t capacity, const HASH &hash, const EQUAL &equal, bslma::Allocator *basicAllocator=0)
Definition bdlc_flathashtable.h:1337
FlatHashTable(bslmf::MovableRef< FlatHashTable > original)
Definition bdlc_flathashtable.h:1427
HASH hash_type
Definition bdlc_flathashtable.h:328
EQUAL key_equal_type
Definition bdlc_flathashtable.h:329
static const bsl::size_t k_MAX_LOAD_FACTOR_NUMERATOR
Definition bdlc_flathashtable.h:403
void reset()
Definition bdlc_flathashtable.h:1806
bsl::pair< iterator, bool > emplace(ARGS &&... args)
iterator find(const KEY &key)
Definition bdlc_flathashtable.h:1741
iterator end()
Definition bdlc_flathashtable.h:1909
bsl::pair< const_iterator, const_iterator > equal_range(const KEY &key) const
Definition bdlc_flathashtable.h:1998
FlatHashTable & operator=(bslmf::MovableRef< FlatHashTable > rhs)
Definition bdlc_flathashtable.h:1542
bool empty() const
Definition bdlc_flathashtable.h:1970
bsl::pair< iterator, bool > try_emplace(const KEY &key, ARGS &&... args)
void insert(INPUT_ITERATOR first, INPUT_ITERATOR last)
Definition bdlc_flathashtable.h:1755
static const bsl::size_t k_MAX_LOAD_FACTOR_DENOMINATOR
Definition bdlc_flathashtable.h:408
ENTRY_UTIL entry_util_type
Definition bdlc_flathashtable.h:327
static const bsl::int8_t k_HASHLET_MASK
Definition bdlc_flathashtable.h:401
bsl::enable_if< bsl::is_convertible< ENTRY_TYPE, ENTRY >::value, bsl::pair< iterator, bool > >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(ENTRY_TYPE) entry)
Definition bdlc_flathashtable.h:564
bslma::Allocator * allocator() const
Return the allocator used by this hash table to supply memory.
Definition bdlc_flathashtable.h:2118
bsl::size_t capacity() const
Definition bdlc_flathashtable.h:1936
bslstl::ForwardIterator< const ENTRY, IteratorImp > const_iterator
Definition bdlc_flathashtable.h:334
bslstl::ForwardIterator< ENTRY, IteratorImp > iterator
Definition bdlc_flathashtable.h:332
const bsl::uint8_t * controls() const
Definition bdlc_flathashtable.h:1955
ENTRY entry_type
Definition bdlc_flathashtable.h:326
ENTRY & operator[](BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key)
Definition bdlc_flathashtable.h:1557
const_iterator find(const KEY &key) const
Definition bdlc_flathashtable.h:2012
FlatHashTable(bslmf::MovableRef< FlatHashTable > original, bslma::Allocator *basicAllocator)
Definition bdlc_flathashtable.h:1449
KEY key_type
Definition bdlc_flathashtable.h:325
EQUAL key_eq() const
Definition bdlc_flathashtable.h:2032
bool contains(const KEY &key) const
Definition bdlc_flathashtable.h:1943
const_iterator begin() const
Definition bdlc_flathashtable.h:2074
iterator begin()
Definition bdlc_flathashtable.h:1892
void reserve(bsl::size_t numEntries)
Definition bdlc_flathashtable.h:1787
const_iterator cend() const
Definition bdlc_flathashtable.h:2100
bsl::size_t size() const
Return the number of entries in this table.
Definition bdlc_flathashtable.h:2064
bsl::size_t count(const KEY &key) const
Definition bdlc_flathashtable.h:1962
FlatHashTable & operator=(const FlatHashTable &rhs)
Definition bdlc_flathashtable.h:1529
~FlatHashTable()
Destroy this object and each of its entries.
Definition bdlc_flathashtable.h:1505
const_iterator end() const
Definition bdlc_flathashtable.h:2108
HASH hash_function() const
Definition bdlc_flathashtable.h:2025
float load_factor() const
Definition bdlc_flathashtable.h:2043
void rehash(bsl::size_t minimumCapacity)
Definition bdlc_flathashtable.h:1766
FlatHashTable(const FlatHashTable &original, bslma::Allocator *basicAllocator=0)
Definition bdlc_flathashtable.h:1380
iterator erase(iterator position)
bsl::pair< iterator, iterator > equal_range(const KEY &key)
Definition bdlc_flathashtable.h:1599
Definition bslstl_pair.h:1210
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:194
Definition bslma_allocator.h:457
virtual void deallocate(void *address)=0
virtual void * allocate(size_type size)=0
Definition bslma_deallocatorproctor.h:312
void release()
Definition bslma_deallocatorproctor.h:384
Definition bslma_destructorguard.h:132
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:751
Definition bslstl_forwarditerator.h:169
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_bitarray.h:503
void swap(BitArray &a, BitArray &b)
bool operator==(const BitArray &lhs, const BitArray &rhs)
bool operator!=(const BitArray &lhs, const BitArray &rhs)
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4126
T::iterator end(T &container)
Definition bslstl_iterator.h:1523
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
static int numTrailingUnsetBits(unsigned int value)
Definition bdlb_bitutil.h:462
static unsigned int withBitCleared(unsigned int value, int index)
Definition bdlb_bitutil.h:581
static int log2(unsigned int value)
Definition bdlb_bitutil.h:338
static unsigned int roundUpToBinaryPower(unsigned int value)
Definition bdlb_bitutil.h:550
Definition bdlc_flathashtable.h:812
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static void destructiveMove(TARGET_TYPE *address, const ALLOCATOR &allocator, TARGET_TYPE *original)
Definition bslma_constructionutil.h:1295
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_isbitwisecopyable.h:298
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