33 #define FOLLY_ATOMICHASHARRAY_H_ 37 #include <boost/iterator/iterator_facade.hpp> 38 #include <boost/noncopyable.hpp> 47 inline size_t operator()(
size_t idx,
size_t ,
size_t capacity)
52 return LIKELY(idx < capacity) ? idx : (idx - capacity);
57 inline size_t operator()(
size_t idx,
size_t numProbes,
size_t capacity)
62 return LIKELY(idx < capacity) ? idx : (idx - capacity);
68 template <
typename NotKeyT,
typename KeyT>
75 template <
typename KeyT>
81 DCHECK_NE(key_in, emptyKey);
82 DCHECK_NE(key_in, lockedKey);
83 DCHECK_NE(key_in, erasedKey);
90 class HashFcn = std::hash<KeyT>,
91 class EqualFcn = std::equal_to<KeyT>,
92 class Allocator = std::allocator<char>,
100 class HashFcn = std::hash<KeyT>,
101 class EqualFcn = std::equal_to<KeyT>,
102 class Allocator = std::allocator<char>,
110 "You are trying to use AtomicHashArray with disallowed key " 111 "types. You must use atomically compare-and-swappable integer " 112 "keys, or a different container class.");
134 template <
class ContT,
class IterVal>
156 typedef std::unique_ptr<AtomicHashArray, Deleter>
SmartPtr;
188 : emptyKey((
KeyT)-1),
193 entryCountThreadCacheSize(1000),
198 static SmartPtr create(
size_t maxSize,
const Config&
c =
Config());
218 typename LookupKeyT = key_type,
219 typename LookupHashFcn = hasher,
220 typename LookupEqualFcn = key_equal>
223 this, findInternal<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k).idx);
227 typename LookupKeyT = key_type,
228 typename LookupHashFcn = hasher,
229 typename LookupEqualFcn = key_equal>
230 const_iterator
find(LookupKeyT
k)
const {
232 ->find<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k);
246 std::pair<iterator, bool>
insert(
const value_type& r) {
247 return emplace(r.first, r.second);
249 std::pair<iterator, bool>
insert(value_type&& r) {
250 return emplace(r.first,
std::move(r.second));
265 typename LookupKeyT = key_type,
266 typename LookupHashFcn = hasher,
267 typename LookupEqualFcn = key_equal,
268 typename LookupKeyToKeyFcn = key_convert,
270 std::pair<iterator, bool>
emplace(LookupKeyT key_in, ArgTs&&... vCtorArgs) {
275 LookupKeyToKeyFcn>(key_in, std::forward<ArgTs>(vCtorArgs)...);
276 return std::make_pair(iterator(
this, ret.
idx), ret.
success);
280 size_t erase(
KeyT k);
289 return numEntries_.readFull() - numErases_.load(std::memory_order_relaxed);
297 iterator it(
this, 0);
302 const_iterator it(
this, 0);
308 return iterator(
this, capacity_);
310 const_iterator
end()
const {
311 return const_iterator(
this, capacity_);
318 DCHECK_LT(idx, capacity_);
319 return iterator(
this, idx);
326 return iterator(
this, idx);
329 return const_iterator(
this, idx);
334 return ((
double)maxEntries_) / capacity_;
338 numEntries_.setCacheSize(newSize);
339 numPendingEntries_.setCacheSize(newSize);
343 return numEntries_.getCacheSize();
365 typename LookupKeyT = key_type,
366 typename LookupHashFcn = hasher,
367 typename LookupEqualFcn = key_equal,
368 typename LookupKeyToKeyFcn =
Identity,
370 SimpleRetT insertInternal(LookupKeyT key, ArgTs&&... vCtorArgs);
373 typename LookupKeyT = key_type,
374 typename LookupHashFcn = hasher,
375 typename LookupEqualFcn = key_equal>
376 SimpleRetT findInternal(
const LookupKeyT key);
378 template <
typename MaybeKeyT>
388 sizeof(std::atomic<KeyT>) ==
sizeof(KeyT),
389 "std::atomic is implemented in an unexpected way for AHM");
390 return const_cast<std::atomic<KeyT>*
>(
391 reinterpret_cast<std::atomic<KeyT>
const*
>(&r.first));
395 return cellKeyPtr(r)->load(std::memory_order_relaxed);
399 return cellKeyPtr(r)->load(std::memory_order_acquire);
413 value_type cells_[0];
422 double maxLoadFactor,
427 inline void unlockCell(value_type*
const cell, KeyT newKey) {
428 cellKeyPtr(*cell)->store(newKey, std::memory_order_release);
433 return cellKeyPtr(*cell)->compare_exchange_strong(
434 expect, kLockedKey_, std::memory_order_acq_rel);
437 template <
class LookupKeyT = key_type,
class LookupHashFcn = hasher>
439 const size_t hashVal = LookupHashFcn()(
k);
440 const size_t probe = hashVal & kAnchorMask_;
441 return LIKELY(probe < capacity_) ? probe : hashVal % capacity_;
const_iterator findAt(uint32_t idx) const
aha_iterator< const AtomicHashArray, const value_type > const_iterator
std::atomic< int64_t > isFull_
const_iterator begin() const
std::ptrdiff_t difference_type
const value_type * const_pointer
std::unique_ptr< AtomicHashArray, Deleter > SmartPtr
void operator()(AtomicHashArray *ptr)
const_iterator makeIter(size_t idx) const
std::pair< const KeyT, ValueT > value_type
std::pair< iterator, bool > insert(value_type &&r)
void checkLegalKeyIfKey(MaybeKeyT key)
constexpr detail::Map< Move > move
ThreadCachedInt< uint64_t > numEntries_
size_t operator()(size_t idx, size_t, size_t capacity) const
—— Concurrent Priority Queue Implementation ——
const_iterator end() const
std::pair< iterator, bool > insert(const value_type &r)
size_t keyToAnchorIdx(const LookupKeyT k) const
void checkLegalKeyIfKeyTImpl(NotKeyT, KeyT, KeyT, KeyT)
bool tryLockCell(value_type *const cell)
static void destroy(AtomicHashArray *)
constexpr auto size(C const &c) -> decltype(c.size())
iterator findAt(uint32_t idx)
uint32_t entryCountThreadCacheSize
void setEntryCountThreadCacheSize(uint32_t newSize)
void unlockCell(value_type *const cell, KeyT newKey)
ThreadCachedInt< uint64_t > numPendingEntries_
void checkLegalKeyIfKeyTImpl(KeyT key_in, KeyT emptyKey, KeyT lockedKey, KeyT erasedKey)
static KeyT relaxedLoadKey(const value_type &r)
uint32_t getEntryCountThreadCacheSize() const
void expect(LineReader &lr, const char *expected)
static const char *const value
static KeyT acquireLoadKey(const value_type &r)
std::pair< iterator, bool > emplace(LookupKeyT key_in, ArgTs &&...vCtorArgs)
iterator find(LookupKeyT k)
double maxLoadFactor() const
static std::atomic< KeyT > * cellKeyPtr(const value_type &r)
const_iterator find(LookupKeyT k) const
KeyConvertFcn key_convert
aha_iterator< AtomicHashArray, value_type > iterator
SimpleRetT(size_t i, bool s)
std::atomic< int64_t > numErases_
const value_type & const_reference
const size_t kAnchorMask_
iterator makeIter(size_t idx)
size_t operator()(size_t idx, size_t numProbes, size_t capacity) const