Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ConcurrentHashmapImpl.h
Go to the documentation of this file.
1 // This file's extension implies that it's C, but it's really -*- C++ -*-.
2 /*
3  * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
4  */
14 #ifndef CXXUTILS_CONCURRENTHASHMAPIMPL_H
15 #define CXXUTILS_CONCURRENTHASHMAPIMPL_H
16 
17 
19 #include "CxxUtils/concepts.h"
20 #include <functional>
21 #include <cstdint>
22 #include <cstdlib>
23 #include <atomic>
24 #include <mutex>
25 #include <memory>
26 #include <new>
27 
28 
29 class ConcurrentHashmapImplTest;
30 
31 
32 namespace CxxUtils {
33 namespace detail {
34 
35 
40 using ConcurrentHashmapVal_t = uintptr_t;
41 
42 
48 template <class T>
49 concept IsConcurrentHashmapPayload = std::is_standard_layout_v<T> &&
50  std::is_trivial_v<T> &&
51  sizeof (T) <= sizeof (ConcurrentHashmapVal_t);
52 
53 
58  : public std::unique_lock<std::mutex>
59 {
60 public:
61  using std::unique_lock<std::mutex>::unique_lock;
62 };
63 
64 
83 template <unsigned ENTRIES_PER_CACHELINE>
85 {
87  static constexpr size_t ENTRIES_PER_CACHELINE_MASK = ENTRIES_PER_CACHELINE-1;
88 
96  CHMTableIterator (size_t hash, size_t mask, size_t maskBits, size_t probeLimit);
97 
98 
102  size_t offset() const;
103 
104 
108  size_t nprobes() const;
109 
110 
116  bool next();
117 
118 
119 private:
122  const size_t m_mask;
124  const size_t m_boffs;
126  const size_t m_stride;
128  const size_t m_probeLimit;
130  size_t m_bucket;
132  size_t m_nprobes;
133 };
134 
135 
194 template <template <class> class UPDATER_,
195  typename HASHER_ = std::hash<uintptr_t>,
196  typename MATCHER_ = std::equal_to<uintptr_t>,
197  uintptr_t NULLVAL_ = 0,
198  uintptr_t TOMBSTONE_ = NULLVAL_>
200 {
201 public:
205  using Hasher_t = HASHER_;
207  using Matcher_t = MATCHER_;
209  static constexpr uintptr_t nullval = NULLVAL_;
211  static constexpr uintptr_t tombstone = TOMBSTONE_;
213  static constexpr size_t INVALID = static_cast<size_t>(-1);
214 
217 
218 
219 private:
221  struct entry_t {
222  std::atomic<val_t> m_key;
223  std::atomic<val_t> m_val;
224  };
225 
227  static constexpr size_t CACHELINE = 64;
228 
229  // Ensure that entries will evenly pack a cache line.
230  // If CACHELINE is a power of two, this implies that sizeof(entry_t)
231  // is as well.
232  static_assert (CACHELINE >= sizeof (entry_t) &&
233  CACHELINE % sizeof(entry_t) == 0);
234 
236  static constexpr size_t ENTRIES_PER_CACHELINE = CACHELINE / sizeof(entry_t);
238  static constexpr size_t ENTRIES_PER_CACHELINE_MASK = (ENTRIES_PER_CACHELINE-1);
239 
241  friend class ::ConcurrentHashmapImplTest;
242 
243 
253  class alignas(CACHELINE) Table
254  {
255  public:
257 
258 
265  Table (size_t capacity,
266  const Hasher_t& hasher = Hasher_t(),
267  const Matcher_t& matcher = Matcher_t());
268 
269 
277  static void* operator new (size_t, size_t capacity);
278 
279 
283  void operator delete (void* p);
284 
285 
293  size_t probeRead (val_t key, size_t hash) const;
294 
295 
307  size_t probeWrite (val_t key, size_t hash, bool& insert);
308 
309 
313  size_t capacity() const;
314 
315 
320  const entry_t& entry (size_t offset) const;
321 
322 
327  entry_t& entry (size_t offset);
328 
329 
330  private:
332  const size_t m_capacity;
334  const size_t m_maxProbe;
336  const size_t m_mask;
338  const size_t m_maskBits;
344  std::atomic<size_t> m_longestProbe;
346  alignas(CACHELINE) entry_t m_entries[1];
347  };
348 
349 
350 public:
352  using Updater_t = UPDATER_<Table>;
354  using Context_t = typename Updater_t::Context_t;
355 
356 
357 
368  size_t capacity_in,
369  const Hasher_t& hasher,
370  const Matcher_t& matcher,
371  const typename Updater_t::Context_t& ctx);
372 
373 
374  // Don't implement copying.
375  // This should be done by derived classes, if desired.
378 
379 
384  size_t size() const;
385 
386 
390  size_t capacity() const;
391 
392 
396  size_t erased() const;
397 
398 
402  const Hasher_t& hasher() const;
403 
404 
408  const Matcher_t& matcher() const;
409 
410 
418  {
419  public:
426  const_iterator (const Table& table, bool end);
427 
428 
435  const_iterator (const Table& table, size_t offset);
436 
437 
441  void next();
442 
443 
447  void prev();
448 
449 
455  val_t key() const;
456 
457 
461  val_t value() const;
462 
463 
467  bool operator!= (const const_iterator& other) const;
468 
469 
473  bool valid() const;
474 
475 
476  private:
478  const Table& m_table;
481  size_t m_offset;
482  };
483 
484 
494 
495 
509  std::pair<const_iterator, bool>
510  put (val_t key, size_t hash, val_t val,
511  bool overwrite,
512  const typename Updater_t::Context_t& ctx);
513 
514 
529  std::pair<const_iterator, bool>
530  put (const Lock_t& lock,
531  val_t key, size_t hash, val_t val,
532  bool overwrite,
533  const typename Updater_t::Context_t& ctx);
534 
535 
543  const_iterator get (val_t key, size_t hash) const;
544 
545 
561  bool erase (val_t key, size_t hash);
562 
563 
580  bool erase (const Lock_t& lock, val_t key, size_t hash);
581 
582 
584  using const_iterator_range = std::pair<const_iterator, const_iterator>;
585 
586 
591 
592 
597 
598 
603 
604 
613  const typename Updater_t::Context_t& ctx);
614 
615 
622  const_iterator clear (const typename Updater_t::Context_t& ctx);
623 
624 
632  void forceClear();
633 
634 
643  void reserve (size_t capacity,
644  const typename Updater_t::Context_t& ctx);
645 
646 
652  void quiescent (const typename Updater_t::Context_t& ctx);
653 
654 
667 
668 
673 
674 
675 private:
682  bool grow (const Lock_t& lock, const typename Updater_t::Context_t& ctx);
683 
684 
692  bool grow (const Lock_t& lock, size_t new_capacity, const typename Updater_t::Context_t& ctx);
693 
694 
696 
697 
707  std::atomic<size_t> m_size;
709  std::atomic<size_t> m_erased;
712 };
713 
714 
715 } // namespace detail
716 
717 
718 } // namespace CxxUtils
719 
720 
722 
723 
724 #endif // not CXXUTILS_CONCURRENTHASHMAPIMPL_H
CxxUtils::detail::ConcurrentHashmapImpl::matcher
const Matcher_t & matcher() const
Return the matcher object.
CxxUtils::detail::ConcurrentHashmapImpl::m_table
Table * m_table
The current table instance. Must be holding the mutex to access this.
Definition: ConcurrentHashmapImpl.h:705
CxxUtils::detail::ConcurrentHashmapImpl::clear
const_iterator clear(size_t capacity, const typename Updater_t::Context_t &ctx)
Erase the table and change the capacity.
CxxUtils::detail::ConcurrentHashmapImpl::operator=
ConcurrentHashmapImpl & operator=(const ConcurrentHashmapImpl &)=delete
CxxUtils::detail::ConcurrentHashmapImpl::Updater_t
UPDATER_< Table > Updater_t
Updater object.
Definition: ConcurrentHashmapImpl.h:352
CxxUtils::detail::ConcurrentHashmapImpl::tombstone
static constexpr uintptr_t tombstone
Tombstone key value. Must be different from nullval to allow erasures.
Definition: ConcurrentHashmapImpl.h:211
CxxUtils::detail::CHMTableIterator::m_stride
const size_t m_stride
Base increment between probes.
Definition: ConcurrentHashmapImpl.h:126
CxxUtils::detail::CHMTableIterator
Helper to generate hash probes.
Definition: ConcurrentHashmapImpl.h:85
CxxUtils::detail::ConcurrentHashmapImpl::entry_t::m_key
std::atomic< val_t > m_key
Definition: ConcurrentHashmapImpl.h:222
CxxUtils::detail::ConcurrentHashmapImpl::entry_t
One entry in the hash table.
Definition: ConcurrentHashmapImpl.h:221
CxxUtils::detail::ConcurrentHashmapVal_t
uintptr_t ConcurrentHashmapVal_t
Type used for keys and values — an unsigned big enough to hold a pointer.
Definition: ConcurrentHashmapImpl.h:40
CxxUtils::detail::ConcurrentHashmapImpl::swap
void swap(ConcurrentHashmapImpl &other)
Swap this container with another.
CxxUtils::detail::ConcurrentHashmapImpl::Table::capacity
size_t capacity() const
The number of entries in the table.
CxxUtils::detail::ConcurrentHashmapImpl::Table::probeWrite
size_t probeWrite(val_t key, size_t hash, bool &insert)
Find a table entry for writing.
CxxUtils::detail::CHMTableIterator::m_nprobes
size_t m_nprobes
Number of probes tried so far.
Definition: ConcurrentHashmapImpl.h:132
CxxUtils::detail::ConcurrentHashmapImpl::erase
bool erase(const Lock_t &lock, val_t key, size_t hash)
Erase an entry from the table, with external locking.
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
CxxUtils::detail::ConcurrentHashmapImpl::Table::entry
const entry_t & entry(size_t offset) const
Return the entry for an offset.
CxxUtils::detail::CHMTableIterator::m_bucket
size_t m_bucket
Index of the start of the cacheline currently being probed.
Definition: ConcurrentHashmapImpl.h:130
CxxUtils::detail::ConcurrentHashmapImpl::Table::Table
Table(size_t capacity, const Hasher_t &hasher=Hasher_t(), const Matcher_t &matcher=Matcher_t())
Constructor.
CxxUtils::detail::ConcurrentHashmapImpl::put
std::pair< const_iterator, bool > put(val_t key, size_t hash, val_t val, bool overwrite, const typename Updater_t::Context_t &ctx)
Add an entry to the table.
CxxUtils::detail::ConcurrentHashmapImpl::erased
size_t erased() const
The number of erased elements in the current table.
detail
Definition: extract_histogram_tag.cxx:14
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::prev
void prev()
Move the iterator back to the previous occupied entry.
CxxUtils::detail::ConcurrentHashmapImpl::Table::probeRead
size_t probeRead(val_t key, size_t hash) const
Find a table entry for reading.
CxxUtils::detail::ConcurrentHashmapImpl::round_up
static uint64_t round_up(uint64_t)
CxxUtils::detail::CHMTableIterator::CHMTableIterator
CHMTableIterator(size_t hash, size_t mask, size_t maskBits, size_t probeLimit)
Constructor.
CxxUtils::detail::ConcurrentHashmapImpl::m_updater
Updater_t m_updater
Updater object managing memory. See above.
Definition: ConcurrentHashmapImpl.h:699
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::next
void next()
Advance the iterator to the next occupied entry.
CxxUtils::detail::ConcurrentHashmapImpl::quiescent
void quiescent(const typename Updater_t::Context_t &ctx)
Called when this thread is no longer referencing anything from this container.
CxxUtils::detail::ConcurrentHashmapImpl
Hash table allowing concurrent, lockless reads.
Definition: ConcurrentHashmapImpl.h:200
atomic_fetch_minmax.h
Atomic min/max functions.
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_matcher
const Matcher_t & m_matcher
The key match object.
Definition: ConcurrentHashmapImpl.h:342
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
CxxUtils::detail::ConcurrentHashmapImpl::CACHELINE
static constexpr size_t CACHELINE
Assumed length in bytes of one cache line.
Definition: ConcurrentHashmapImpl.h:227
CxxUtils::detail::ConcurrentHashmapImpl::forceClear
void forceClear()
Erase the table by filling it with nulls.
CxxUtils::detail::ConcurrentHashmapImpl::val_t
ConcurrentHashmapVal_t val_t
Type used for keys and values — an unsigned big enough to hold a pointer.
Definition: ConcurrentHashmapImpl.h:203
CxxUtils::detail::ConcurrentHashmapImpl::capacity
size_t capacity() const
Return the current table size.
CxxUtils::detail::ConcurrentHashmapImpl::Table
Table of hash entries.
Definition: ConcurrentHashmapImpl.h:254
CxxUtils::detail::ConcurrentHashmapImpl::nullval
static constexpr uintptr_t nullval
Null key value.
Definition: ConcurrentHashmapImpl.h:209
CxxUtils::detail::ConcurrentHashmapImpl::Context_t
typename Updater_t::Context_t Context_t
Context type for the updater.
Definition: ConcurrentHashmapImpl.h:354
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::key
val_t key() const
Return the key for this iterator.
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::m_offset
size_t m_offset
The current position in the table.
Definition: ConcurrentHashmapImpl.h:481
operator!=
bool operator!=(const DataVector< T > &a, const DataVector< T > &b)
Based on operator==.
CxxUtils::detail::ConcurrentHashmapImpl::grow
bool grow(const Lock_t &lock, const typename Updater_t::Context_t &ctx)
Make the table larger.
CxxUtils::detail::ConcurrentHashmapImpl::range
const_iterator_range range() const
Return a range that can be used to iterate over the container.
CxxUtils::detail::ConcurrentHashmapImpl::ENTRIES_PER_CACHELINE
static constexpr size_t ENTRIES_PER_CACHELINE
Number of entries in one cache line.
Definition: ConcurrentHashmapImpl.h:236
CxxUtils::detail::ConcurrentHashmapImpl::size
size_t size() const
Return the number of items currently stored.
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::detail::ConcurrentHashmapImpl::entry_t::m_val
std::atomic< val_t > m_val
Definition: ConcurrentHashmapImpl.h:223
CxxUtils::detail::ConcurrentHashmapImpl::ConcurrentHashmapImpl
ConcurrentHashmapImpl(const ConcurrentHashmapImpl &)=delete
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::const_iterator
const_iterator(const Table &table, bool end)
Constructor.
CxxUtils::detail::ConcurrentHashmapImpl::ConcurrentHashmapImpl
ConcurrentHashmapImpl(Updater_t &&updater, size_t capacity_in, const Hasher_t &hasher, const Matcher_t &matcher, const typename Updater_t::Context_t &ctx)
Constructor.
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_mask
const size_t m_mask
Mask for table indices (capacity-1).
Definition: ConcurrentHashmapImpl.h:336
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
CxxUtils::detail::ConcurrentHashmapImpl::lock
Lock_t lock()
Take a lock on the container.
CxxUtils::detail::ConcurrentHashmapImpl::get
const_iterator get(val_t key, size_t hash) const
Look up an entry in the table.
CxxUtils::detail::CHMTableIterator::m_boffs
const size_t m_boffs
Offset of the first entry we probe within its cacheline.
Definition: ConcurrentHashmapImpl.h:124
CxxUtils::detail::ConcurrentHashmapImpl::erase
bool erase(val_t key, size_t hash)
Erase an entry from the table.
ConcurrentHashmapImpl.icc
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator
Bidirectional iterator over occupied table entries.
Definition: ConcurrentHashmapImpl.h:418
CxxUtils::detail::ConcurrentHashmapImpl::m_size
std::atomic< size_t > m_size
Number of entries in the map.
Definition: ConcurrentHashmapImpl.h:707
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_maskBits
const size_t m_maskBits
Number of bits in the mask.
Definition: ConcurrentHashmapImpl.h:338
CxxUtils::detail::IsConcurrentHashmapPayload
concept IsConcurrentHashmapPayload
Concept for a value that can be saved in a concurrent hash map.
Definition: ConcurrentHashmapImpl.h:49
CxxUtils::detail::ConcurrentHashmapImpl::Table::entry
entry_t & entry(size_t offset)
Return the entry for an offset (non-const).
python.ext.table_printer.table
list table
Definition: table_printer.py:81
CxxUtils::detail::ConcurrentHashmapImpl::m_hasher
const Hasher_t m_hasher
The hash object.
Definition: ConcurrentHashmapImpl.h:701
CxxUtils::detail::ConcurrentHashmapImpl::m_matcher
const Matcher_t m_matcher
The key match object.
Definition: ConcurrentHashmapImpl.h:703
CxxUtils::detail::CHMTableIterator::next
bool next()
Move to the next probe.
CxxUtils::detail::ConcurrentHashmapImpl::m_erased
std::atomic< size_t > m_erased
Number of entries that have been erased.
Definition: ConcurrentHashmapImpl.h:709
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::m_table
const Table & m_table
The table over which we're iterating.
Definition: ConcurrentHashmapImpl.h:478
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_capacity
const size_t m_capacity
Number of entries in the table. Must be a power of 2.
Definition: ConcurrentHashmapImpl.h:332
CxxUtils::detail::CHMTableIterator::ENTRIES_PER_CACHELINE_MASK
static constexpr size_t ENTRIES_PER_CACHELINE_MASK
Mask for the within-cacheline part of indices.
Definition: ConcurrentHashmapImpl.h:87
CxxUtils::detail::ConcurrentHashmapImpl::grow
bool grow(const Lock_t &lock, size_t new_capacity, const typename Updater_t::Context_t &ctx)
Make the table larger.
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::valid
bool valid() const
Check that the iterator is valid (not pointing at the end).
CxxUtils::detail::CHMTableIterator::offset
size_t offset() const
Offset of the element currently being probed.
concepts.h
A couple standard-library related concepts.
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::const_iterator
const_iterator(const Table &table, size_t offset)
Constructor.
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
CxxUtils::detail::ConcurrentHashmapImpl::ENTRIES_PER_CACHELINE_MASK
static constexpr size_t ENTRIES_PER_CACHELINE_MASK
Mask for the cache line part of an index.
Definition: ConcurrentHashmapImpl.h:238
CxxUtils::detail::ConcurrentHashmapImpl::begin
const_iterator begin() const
A begin iterator for the container.
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
CxxUtils::detail::CHMTableIterator::m_mask
const size_t m_mask
Mask for the table; i.e., capacity-1, but with the low bits corresponding to ENTRIES_PER_CACHELINE al...
Definition: ConcurrentHashmapImpl.h:122
CxxUtils::detail::HashmapLock
Helper to allow for external locking with put().
Definition: ConcurrentHashmapImpl.h:59
CxxUtils::detail::ConcurrentHashmapImpl::INVALID
static constexpr size_t INVALID
Used to represent an invalid table index.
Definition: ConcurrentHashmapImpl.h:213
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator_range
std::pair< const_iterator, const_iterator > const_iterator_range
Two iterators defining a range.
Definition: ConcurrentHashmapImpl.h:584
CxxUtils::detail::ConcurrentHashmapImpl::end
const_iterator end() const
An end iterator for the container.
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
CxxUtils::detail::ConcurrentHashmapImpl::put
std::pair< const_iterator, bool > put(const Lock_t &lock, val_t key, size_t hash, val_t val, bool overwrite, const typename Updater_t::Context_t &ctx)
Add an entry to the table, with external locking.
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_longestProbe
std::atomic< size_t > m_longestProbe
Longest probe needed so far.
Definition: ConcurrentHashmapImpl.h:344
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
CxxUtils::detail::ConcurrentHashmapImpl::const_iterator::value
val_t value() const
Return the value for this iterator.
CxxUtils::detail::ConcurrentHashmapImpl::Hasher_t
HASHER_ Hasher_t
Hash object.
Definition: ConcurrentHashmapImpl.h:205
CxxUtils::detail::ConcurrentHashmapImpl::Matcher_t
MATCHER_ Matcher_t
Key match object.
Definition: ConcurrentHashmapImpl.h:207
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_maxProbe
const size_t m_maxProbe
Maximum number of probes allowed before resizing the table.
Definition: ConcurrentHashmapImpl.h:334
CxxUtils::detail::ConcurrentHashmapImpl::Table::m_hasher
const Hasher_t & m_hasher
The hash object.
Definition: ConcurrentHashmapImpl.h:340
CxxUtils::detail::ConcurrentHashmapImpl::updater
Updater_t & updater()
Access the Updater instance.
CxxUtils::detail::ConcurrentHashmapImpl::clear
const_iterator clear(const typename Updater_t::Context_t &ctx)
Erase the table (don't change the capacity).
CxxUtils::detail::ConcurrentHashmapImpl::m_mutex
std::mutex m_mutex
Mutex to serialize changes to the map.
Definition: ConcurrentHashmapImpl.h:711
CxxUtils::detail::CHMTableIterator::nprobes
size_t nprobes() const
Return the number of probes performed so far.
CxxUtils::detail::CHMTableIterator::m_probeLimit
const size_t m_probeLimit
Maximum number of probes to try.
Definition: ConcurrentHashmapImpl.h:128
CxxUtils::detail::ConcurrentHashmapImpl::reserve
void reserve(size_t capacity, const typename Updater_t::Context_t &ctx)
Increase the table capacity.
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
CxxUtils::detail::ConcurrentHashmapImpl::hasher
const Hasher_t & hasher() const
Return the hasher object.