proxygen
folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex > Class Template Reference

#include <ConcurrentHashMap-detail.h>

Classes

class  Buckets
 
class  Iterator
 

Public Types

typedef KeyType key_type
 
typedef ValueType mapped_type
 
typedef std::pair< const KeyType, ValueType > value_type
 
typedef std::size_t size_type
 
using Node = concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom >
 

Public Member Functions

 ConcurrentHashMapSegment (size_t initial_buckets, float load_factor, size_t max_size)
 
 ~ConcurrentHashMapSegment ()
 
size_t size ()
 
bool empty ()
 
bool insert (Iterator &it, std::pair< key_type, mapped_type > &&foo)
 
template<typename Key , typename Value >
bool insert (Iterator &it, Key &&k, Value &&v)
 
template<typename Key , typename... Args>
bool try_emplace (Iterator &it, Key &&k, Args &&...args)
 
template<typename... Args>
bool emplace (Iterator &it, const KeyType &k, Node *node)
 
template<typename Key , typename Value >
bool insert_or_assign (Iterator &it, Key &&k, Value &&v)
 
template<typename Key , typename Value >
bool assign (Iterator &it, Key &&k, Value &&v)
 
template<typename Key , typename Value >
bool assign_if_equal (Iterator &it, Key &&k, const ValueType &expected, Value &&desired)
 
template<typename MatchFunc , typename... Args>
bool insert_internal (Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
 
void rehash (size_t bucket_count)
 
bool find (Iterator &res, const KeyType &k)
 
size_type erase (const key_type &key)
 
size_type erase_internal (const key_type &key, Iterator *iter)
 
void erase (Iterator &res, Iterator &pos)
 
void clear ()
 
void max_load_factor (float factor)
 
Iterator cbegin ()
 
Iterator cend ()
 

Private Types

enum  InsertType { InsertType::DOES_NOT_EXIST, InsertType::MUST_EXIST, InsertType::ANY, InsertType::MATCH }
 

Private Member Functions

uint64_t getIdx (size_t bucket_count, size_t hash)
 
void getBucketsAndCount (size_t &bcount, Buckets *&buckets, hazptr_holder< Atom > &hazptr)
 

Private Attributes

Mutex m_
 
float load_factor_
 
size_t load_factor_nodes_
 
size_t size_ {0}
 
size_t const max_size_
 
Atom< Buckets * > buckets_ {nullptr}
 
std::atomic< uint64_tseqlock_ {0}
 
Atom< size_t > bucket_count_
 

Detailed Description

template<typename KeyType, typename ValueType, uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
class folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >

Definition at line 208 of file ConcurrentHashMap-detail.h.

Member Typedef Documentation

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
typedef KeyType folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::key_type

Definition at line 219 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
typedef ValueType folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::mapped_type

Definition at line 220 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
using folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Node = concurrenthashmap::NodeT<KeyType, ValueType, Allocator, Atom>

Definition at line 224 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
typedef std::size_t folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::size_type

Definition at line 222 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
typedef std::pair<const KeyType, ValueType> folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::value_type

Definition at line 221 of file ConcurrentHashMap-detail.h.

Member Enumeration Documentation

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
enum folly::detail::ConcurrentHashMapSegment::InsertType
strongprivate
Enumerator
DOES_NOT_EXIST 
MUST_EXIST 
ANY 
MATCH 

Definition at line 209 of file ConcurrentHashMap-detail.h.

209  {
210  DOES_NOT_EXIST, // insert/emplace operations. If key exists, return false.
211  MUST_EXIST, // assign operations. If key does not exist, return false.
212  ANY, // insert_or_assign.
213  MATCH, // assign_if_equal (not in std). For concurrent maps, a
214  // way to atomically change a value if equal to some other
215  // value.
216  };

Constructor & Destructor Documentation

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::ConcurrentHashMapSegment ( size_t  initial_buckets,
float  load_factor,
size_t  max_size 
)
inline

Definition at line 227 of file ConcurrentHashMap-detail.h.

References folly::isPowTwo(), folly::nextPowTwo(), and folly::popcount().

231  : load_factor_(load_factor), max_size_(max_size) {
232  initial_buckets = folly::nextPowTwo(initial_buckets);
233  DCHECK(
234  max_size_ == 0 ||
235  (isPowTwo(max_size_) &&
236  (folly::popcount(max_size_ - 1) + ShardBits <= 32)));
237  auto buckets = Buckets::create(initial_buckets);
238  buckets_.store(buckets, std::memory_order_release);
239  load_factor_nodes_ = initial_buckets * load_factor_;
240  bucket_count_.store(initial_buckets, std::memory_order_relaxed);
241  }
constexpr unsigned int popcount(T const v)
Definition: Bits.h:130
constexpr T nextPowTwo(T const v)
Definition: Bits.h:149
constexpr bool isPowTwo(T const v)
Definition: Bits.h:161
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::~ConcurrentHashMapSegment ( )
inline

Definition at line 243 of file ConcurrentHashMap-detail.h.

References count.

243  {
244  auto buckets = buckets_.load(std::memory_order_relaxed);
245  // We can delete and not retire() here, since users must have
246  // their own synchronization around destruction.
247  auto count = bucket_count_.load(std::memory_order_relaxed);
248  buckets->unlink_and_reclaim_nodes(count);
249  buckets->destroy(count);
250  }
int * count

Member Function Documentation

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename Key , typename Value >
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::assign ( Iterator it,
Key &&  k,
Value &&  v 
)
inline

Definition at line 326 of file ConcurrentHashMap-detail.h.

References k, uint8_t, and v.

326  {
327  auto node = (Node*)Allocator().allocate(sizeof(Node));
328  new (node) Node(std::forward<Key>(k), std::forward<Value>(v));
329  auto res = insert_internal(
330  it,
331  node->getItem().first,
333  [](const ValueType&) { return false; },
334  node,
335  node);
336  if (!res) {
337  node->~Node();
338  Allocator().deallocate((uint8_t*)node, sizeof(Node));
339  }
340  return res;
341  }
auto v
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename Key , typename Value >
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::assign_if_equal ( Iterator it,
Key &&  k,
const ValueType &  expected,
Value &&  desired 
)
inline

Definition at line 344 of file ConcurrentHashMap-detail.h.

References testing::Args(), k, uint8_t, and v.

348  {
349  auto node = (Node*)Allocator().allocate(sizeof(Node));
350  new (node) Node(std::forward<Key>(k), std::forward<Value>(desired));
351  auto res = insert_internal(
352  it,
353  node->getItem().first,
355  [&expected](const ValueType& v) { return v == expected; },
356  node,
357  node);
358  if (!res) {
359  node->~Node();
360  Allocator().deallocate((uint8_t*)node, sizeof(Node));
361  }
362  return res;
363  }
auto v
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
Iterator folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::cbegin ( )
inline

Definition at line 634 of file ConcurrentHashMap-detail.h.

References folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::hazptrs_, folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::next(), and folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::setNode().

634  {
635  Iterator res;
636  size_t bcount;
637  Buckets* buckets;
638  getBucketsAndCount(bcount, buckets, res.hazptrs_[0]);
639  res.setNode(nullptr, buckets, bcount, 0);
640  res.next();
641  return res;
642  }
void getBucketsAndCount(size_t &bcount, Buckets *&buckets, hazptr_holder< Atom > &hazptr)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
Iterator folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::cend ( )
inline
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
void folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::clear ( )
inline

Definition at line 614 of file ConcurrentHashMap-detail.h.

References g(), and folly::hazptr_obj_base< T, Atom, D >::retire().

614  {
615  size_t bcount = bucket_count_.load(std::memory_order_relaxed);
616  Buckets* buckets;
617  auto newbuckets = Buckets::create(bcount);
618  {
619  std::lock_guard<Mutex> g(m_);
620  buckets = buckets_.load(std::memory_order_relaxed);
621  buckets_.store(newbuckets, std::memory_order_release);
622  size_ = 0;
623  }
624  buckets->retire(concurrenthashmap::HazptrBucketDeleter<Allocator>(bcount));
625  }
g_t g(f_t)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename... Args>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::emplace ( Iterator it,
const KeyType &  k,
Node node 
)
inline

Definition at line 297 of file ConcurrentHashMap-detail.h.

Referenced by folly::ConcurrentHashMap< KeyType, ValueType, HashFn, KeyEqual, Allocator, ShardBits, Atom, Mutex >::emplace().

297  {
298  return insert_internal(
299  it,
300  k,
302  [](const ValueType&) { return false; },
303  node,
304  node);
305  }
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::empty ( )
inline

Definition at line 256 of file ConcurrentHashMap-detail.h.

References folly::size().

256  {
257  return size() == 0;
258  }
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_type folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::erase ( const key_type key)
inline

Definition at line 548 of file ConcurrentHashMap-detail.h.

Referenced by folly::ConcurrentHashMap< KeyType, ValueType, HashFn, KeyEqual, Allocator, ShardBits, Atom, Mutex >::erase().

548  {
549  return erase_internal(key, nullptr);
550  }
size_type erase_internal(const key_type &key, Iterator *iter)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
void folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::erase ( Iterator res,
Iterator pos 
)
inline

Definition at line 608 of file ConcurrentHashMap-detail.h.

References folly::padded::cend().

608  {
609  erase_internal(pos->first, &res);
610  // Invalidate the iterator.
611  pos = cend();
612  }
size_type erase_internal(const key_type &key, Iterator *iter)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_type folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::erase_internal ( const key_type key,
Iterator iter 
)
inline

Definition at line 552 of file ConcurrentHashMap-detail.h.

References g(), h, folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::hazptrs_, cpp.ast::next(), folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::next(), folly::detail::concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom >::next_, and folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::setNode().

552  {
553  Node* node{nullptr};
554  auto h = HashFn()(key);
555  {
556  std::lock_guard<Mutex> g(m_);
557 
558  size_t bcount = bucket_count_.load(std::memory_order_relaxed);
559  auto buckets = buckets_.load(std::memory_order_relaxed);
560  auto idx = getIdx(bcount, h);
561  auto head = &buckets->buckets_[idx]();
562  node = head->load(std::memory_order_relaxed);
563  Node* prev = nullptr;
564  while (node) {
565  if (KeyEqual()(key, node->getItem().first)) {
566  auto next = node->next_.load(std::memory_order_relaxed);
567  if (next) {
568  next->acquire_link(); // defined in hazptr_obj_base_linked
569  }
570  if (prev) {
571  prev->next_.store(next, std::memory_order_release);
572  } else {
573  // Must be head of list.
574  head->store(next, std::memory_order_release);
575  }
576 
577  if (iter) {
578  iter->hazptrs_[0].reset(buckets);
579  iter->setNode(
580  node->next_.load(std::memory_order_acquire),
581  buckets,
582  bcount,
583  idx);
584  iter->next();
585  }
586  size_--;
587  break;
588  }
589  prev = node;
590  node = node->next_.load(std::memory_order_relaxed);
591  }
592  }
593  // Delete the node while not under the lock.
594  if (node) {
595  node->release();
596  return 1;
597  }
598 
599  return 0;
600  }
*than *hazptr_holder h
Definition: Hazptr.h:116
Atom< Node< Atom > * > next_
Definition: HazptrTest.cpp:100
g_t g(f_t)
uint64_t getIdx(size_t bucket_count, size_t hash)
def next(obj)
Definition: ast.py:58
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::find ( Iterator res,
const KeyType &  k 
)
inline

Definition at line 525 of file ConcurrentHashMap-detail.h.

References folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Buckets::buckets_, h, folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::hazptrs_, k, and folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::setNode().

525  {
526  auto& hazcurr = res.hazptrs_[1];
527  auto& haznext = res.hazptrs_[2];
528  auto h = HashFn()(k);
529  size_t bcount;
530  Buckets* buckets;
531  getBucketsAndCount(bcount, buckets, res.hazptrs_[0]);
532 
533  auto idx = getIdx(bcount, h);
534  auto prev = &buckets->buckets_[idx]();
535  auto node = hazcurr.get_protected(*prev);
536  while (node) {
537  if (KeyEqual()(k, node->getItem().first)) {
538  res.setNode(node, buckets, bcount, idx);
539  return true;
540  }
541  node = haznext.get_protected(node->next_);
542  hazcurr.swap(haznext);
543  }
544  return false;
545  }
*than *hazptr_holder h
Definition: Hazptr.h:116
void getBucketsAndCount(size_t &bcount, Buckets *&buckets, hazptr_holder< Atom > &hazptr)
KeyT k
uint64_t getIdx(size_t bucket_count, size_t hash)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
void folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::getBucketsAndCount ( size_t &  bcount,
Buckets *&  buckets,
hazptr_holder< Atom > &  hazptr 
)
inlineprivate

Definition at line 795 of file ConcurrentHashMap-detail.h.

References folly::hazptr_holder< Atom >::get_protected().

798  {
799  while (true) {
800  auto seqlock = seqlock_.load(std::memory_order_acquire);
801  bcount = bucket_count_.load(std::memory_order_acquire);
802  buckets = hazptr.get_protected(buckets_);
803  auto seqlock2 = seqlock_.load(std::memory_order_acquire);
804  if (!(seqlock & 1) && (seqlock == seqlock2)) {
805  break;
806  }
807  }
808  DCHECK(buckets);
809  }
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
uint64_t folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::getIdx ( size_t  bucket_count,
size_t  hash 
)
inlineprivate

Definition at line 792 of file ConcurrentHashMap-detail.h.

792  {
793  return (hash >> ShardBits) & (bucket_count - 1);
794  }
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::insert ( Iterator it,
std::pair< key_type, mapped_type > &&  foo 
)
inline

Definition at line 260 of file ConcurrentHashMap-detail.h.

References folly::gen::move.

Referenced by folly::ConcurrentHashMap< KeyType, ValueType, HashFn, KeyEqual, Allocator, ShardBits, Atom, Mutex >::insert().

260  {
261  return insert(it, std::move(foo.first), std::move(foo.second));
262  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool insert(Iterator &it, std::pair< key_type, mapped_type > &&foo)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename Key , typename Value >
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::insert ( Iterator it,
Key &&  k,
Value &&  v 
)
inline

Definition at line 265 of file ConcurrentHashMap-detail.h.

References testing::Args(), k, testing::Key(), uint8_t, and v.

265  {
266  auto node = (Node*)Allocator().allocate(sizeof(Node));
267  new (node) Node(std::forward<Key>(k), std::forward<Value>(v));
268  auto res = insert_internal(
269  it,
270  node->getItem().first,
272  [](const ValueType&) { return false; },
273  node,
274  node);
275  if (!res) {
276  node->~Node();
277  Allocator().deallocate((uint8_t*)node, sizeof(Node));
278  }
279  return res;
280  }
auto v
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename MatchFunc , typename... Args>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::insert_internal ( Iterator it,
const KeyType &  k,
InsertType  type,
MatchFunc  match,
Node cur,
Args &&...  args 
)
inline

Definition at line 366 of file ConcurrentHashMap-detail.h.

References g(), h, folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::hazptrs_, k, cpp.ast::next(), folly::detail::concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom >::next_, and folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::Iterator::setNode().

372  {
373  auto h = HashFn()(k);
374  std::unique_lock<Mutex> g(m_);
375 
376  size_t bcount = bucket_count_.load(std::memory_order_relaxed);
377  auto buckets = buckets_.load(std::memory_order_relaxed);
378  // Check for rehash needed for DOES_NOT_EXIST
380  if (max_size_ && size_ << 1 > max_size_) {
381  // Would exceed max size.
382  throw std::bad_alloc();
383  }
384  rehash(bcount << 1);
385  buckets = buckets_.load(std::memory_order_relaxed);
386  bcount = bucket_count_.load(std::memory_order_relaxed);
387  }
388 
389  auto idx = getIdx(bcount, h);
390  auto head = &buckets->buckets_[idx]();
391  auto node = head->load(std::memory_order_relaxed);
392  auto headnode = node;
393  auto prev = head;
394  auto& hazbuckets = it.hazptrs_[0];
395  auto& haznode = it.hazptrs_[1];
396  hazbuckets.reset(buckets);
397  while (node) {
398  // Is the key found?
399  if (KeyEqual()(k, node->getItem().first)) {
400  it.setNode(node, buckets, bcount, idx);
401  haznode.reset(node);
402  if (type == InsertType::MATCH) {
403  if (!match(node->getItem().second)) {
404  return false;
405  }
406  }
408  return false;
409  } else {
410  if (!cur) {
411  cur = (Node*)Allocator().allocate(sizeof(Node));
412  new (cur) Node(std::forward<Args>(args)...);
413  }
414  auto next = node->next_.load(std::memory_order_relaxed);
415  cur->next_.store(next, std::memory_order_relaxed);
416  if (next) {
417  next->acquire_link(); // defined in hazptr_obj_base_linked
418  }
419  prev->store(cur, std::memory_order_release);
420  g.unlock();
421  // Release not under lock.
422  node->release();
423  return true;
424  }
425  }
426 
427  prev = &node->next_;
428  node = node->next_.load(std::memory_order_relaxed);
429  }
431  haznode.reset();
432  hazbuckets.reset();
433  return false;
434  }
435  // Node not found, check for rehash on ANY
437  if (max_size_ && size_ << 1 > max_size_) {
438  // Would exceed max size.
439  throw std::bad_alloc();
440  }
441  rehash(bcount << 1);
442 
443  // Reload correct bucket.
444  buckets = buckets_.load(std::memory_order_relaxed);
445  bcount <<= 1;
446  hazbuckets.reset(buckets);
447  idx = getIdx(bcount, h);
448  head = &buckets->buckets_[idx]();
449  headnode = head->load(std::memory_order_relaxed);
450  }
451 
452  // We found a slot to put the node.
453  size_++;
454  if (!cur) {
455  // InsertType::ANY
456  // OR DOES_NOT_EXIST, but only in the try_emplace case
458  cur = (Node*)Allocator().allocate(sizeof(Node));
459  new (cur) Node(std::forward<Args>(args)...);
460  }
461  cur->next_.store(headnode, std::memory_order_relaxed);
462  head->store(cur, std::memory_order_release);
463  it.setNode(cur, buckets, bcount, idx);
464  return true;
465  }
*than *hazptr_holder h
Definition: Hazptr.h:116
PskType type
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
Atom< Node< Atom > * > next_
Definition: HazptrTest.cpp:100
g_t g(f_t)
KeyT k
uint64_t getIdx(size_t bucket_count, size_t hash)
def next(obj)
Definition: ast.py:58
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename Key , typename Value >
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::insert_or_assign ( Iterator it,
Key &&  k,
Value &&  v 
)
inline

Definition at line 308 of file ConcurrentHashMap-detail.h.

References k, uint8_t, and v.

Referenced by folly::ConcurrentHashMap< KeyType, ValueType, HashFn, KeyEqual, Allocator, ShardBits, Atom, Mutex >::insert_or_assign().

308  {
309  auto node = (Node*)Allocator().allocate(sizeof(Node));
310  new (node) Node(std::forward<Key>(k), std::forward<Value>(v));
311  auto res = insert_internal(
312  it,
313  node->getItem().first,
315  [](const ValueType&) { return false; },
316  node,
317  node);
318  if (!res) {
319  node->~Node();
320  Allocator().deallocate((uint8_t*)node, sizeof(Node));
321  }
322  return res;
323  }
auto v
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
void folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::max_load_factor ( float  factor)
inline

Definition at line 627 of file ConcurrentHashMap-detail.h.

References g().

627  {
628  std::lock_guard<Mutex> g(m_);
629  load_factor_ = factor;
631  bucket_count_.load(std::memory_order_relaxed) * load_factor_;
632  }
g_t g(f_t)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
void folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::rehash ( size_t  bucket_count)
inline

Definition at line 468 of file ConcurrentHashMap-detail.h.

References count, h, i, and k.

468  {
469  auto buckets = buckets_.load(std::memory_order_relaxed);
470  auto newbuckets = Buckets::create(bucket_count);
471 
472  load_factor_nodes_ = bucket_count * load_factor_;
473 
474  auto oldcount = bucket_count_.load(std::memory_order_relaxed);
475  for (size_t i = 0; i < oldcount; i++) {
476  auto bucket = &buckets->buckets_[i]();
477  auto node = bucket->load(std::memory_order_relaxed);
478  if (!node) {
479  continue;
480  }
481  auto h = HashFn()(node->getItem().first);
482  auto idx = getIdx(bucket_count, h);
483  // Reuse as long a chain as possible from the end. Since the
484  // nodes don't have previous pointers, the longest last chain
485  // will be the same for both the previous hashmap and the new one,
486  // assuming all the nodes hash to the same bucket.
487  auto lastrun = node;
488  auto lastidx = idx;
489  auto count = 0;
490  auto last = node->next_.load(std::memory_order_relaxed);
491  for (; last != nullptr;
492  last = last->next_.load(std::memory_order_relaxed)) {
493  auto k = getIdx(bucket_count, HashFn()(last->getItem().first));
494  if (k != lastidx) {
495  lastidx = k;
496  lastrun = last;
497  count = 0;
498  }
499  count++;
500  }
501  // Set longest last run in new bucket, incrementing the refcount.
502  lastrun->acquire_link(); // defined in hazptr_obj_base_linked
503  newbuckets->buckets_[lastidx]().store(lastrun, std::memory_order_relaxed);
504  // Clone remaining nodes
505  for (; node != lastrun;
506  node = node->next_.load(std::memory_order_relaxed)) {
507  auto newnode = (Node*)Allocator().allocate(sizeof(Node));
508  new (newnode) Node(node);
509  auto k = getIdx(bucket_count, HashFn()(node->getItem().first));
510  auto prevhead = &newbuckets->buckets_[k]();
511  newnode->next_.store(prevhead->load(std::memory_order_relaxed));
512  prevhead->store(newnode, std::memory_order_relaxed);
513  }
514  }
515 
516  auto oldbuckets = buckets_.load(std::memory_order_relaxed);
517  seqlock_.fetch_add(1, std::memory_order_release);
518  bucket_count_.store(bucket_count, std::memory_order_release);
519  buckets_.store(newbuckets, std::memory_order_release);
520  seqlock_.fetch_add(1, std::memory_order_release);
521  oldbuckets->retire(
522  concurrenthashmap::HazptrBucketDeleter<Allocator>(oldcount));
523  }
*than *hazptr_holder h
Definition: Hazptr.h:116
concurrenthashmap::NodeT< KeyType, ValueType, Allocator, Atom > Node
int * count
KeyT k
uint64_t getIdx(size_t bucket_count, size_t hash)
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_t folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::size ( )
inline

Definition at line 252 of file ConcurrentHashMap-detail.h.

252  {
253  return size_;
254  }
template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
template<typename Key , typename... Args>
bool folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::try_emplace ( Iterator it,
Key &&  k,
Args &&...  args 
)
inline

Definition at line 283 of file ConcurrentHashMap-detail.h.

References testing::Args(), and k.

Referenced by folly::ConcurrentHashMap< KeyType, ValueType, HashFn, KeyEqual, Allocator, ShardBits, Atom, Mutex >::try_emplace().

283  {
284  // Note: first key is only ever compared. Second is moved in to
285  // create the node, and the first key is never touched again.
286  return insert_internal(
287  it,
288  std::forward<Key>(k),
290  [](const ValueType&) { return false; },
291  nullptr,
292  std::forward<Key>(k),
293  std::forward<Args>(args)...);
294  }
bool insert_internal(Iterator &it, const KeyType &k, InsertType type, MatchFunc match, Node *cur, Args &&...args)
KeyT k

Member Data Documentation

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
Atom<size_t> folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::bucket_count_
private

Definition at line 820 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
Atom<Buckets*> folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::buckets_ {nullptr}
private

Definition at line 818 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
float folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::load_factor_
private

Definition at line 812 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_t folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::load_factor_nodes_
private

Definition at line 813 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
Mutex folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::m_
private

Definition at line 811 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_t const folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::max_size_
private

Definition at line 815 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
std::atomic<uint64_t> folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::seqlock_ {0}
private

Definition at line 819 of file ConcurrentHashMap-detail.h.

template<typename KeyType , typename ValueType , uint8_t ShardBits = 0, typename HashFn = std::hash<KeyType>, typename KeyEqual = std::equal_to<KeyType>, typename Allocator = std::allocator<uint8_t>, template< typename > class Atom = std::atomic, class Mutex = std::mutex>
size_t folly::detail::ConcurrentHashMapSegment< KeyType, ValueType, ShardBits, HashFn, KeyEqual, Allocator, Atom, Mutex >::size_ {0}
private

Definition at line 814 of file ConcurrentHashMap-detail.h.


The documentation for this class was generated from the following file: