// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_SAMPLING_HEAP_PROFILER_LOCK_FREE_ADDRESS_HASH_SET_H_ #define BASE_SAMPLING_HEAP_PROFILER_LOCK_FREE_ADDRESS_HASH_SET_H_ #include <atomic> #include <cstdint> #include <vector> #include "base/base_export.h" #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/memory/raw_ptr_exclusion.h" namespace base { // A hash set container that provides lock-free version of |Contains| operation. // It does not support concurrent write operations |Insert| and |Remove|. // All write operations if performed from multiple threads must be properly // guarded with a lock. // |Contains| method can be executed concurrently with other |Insert|, |Remove|, // or |Contains| even over the same key. // However, please note the result of concurrent execution of |Contains| // with |Insert| or |Remove| over the same key is racy. // // The hash set never rehashes, so the number of buckets stays the same // for the lifetime of the set. // // Internally the hashset is implemented as a vector of N buckets // (N has to be a power of 2). Each bucket holds a single-linked list of // nodes each corresponding to a key. // It is not possible to really delete nodes from the list as there might // be concurrent reads being executed over the node. The |Remove| operation // just marks the node as empty by placing nullptr into its key field. // Consequent |Insert| operations may reuse empty nodes when possible. // // The structure of the hashset for N buckets is the following: // 0: {*}--> {key1,*}--> {key2,*}--> NULL // 1: {*}--> NULL // 2: {*}--> {NULL,*}--> {key3,*}--> {key4,*}--> NULL // ... // N-1: {*}--> {keyM,*}--> NULL class BASE_EXPORT LockFreeAddressHashSet { … }; ALWAYS_INLINE LockFreeAddressHashSet::Node::Node(void* key, Node* next) : … { … } ALWAYS_INLINE bool LockFreeAddressHashSet::Contains(void* key) const { … } ALWAYS_INLINE void LockFreeAddressHashSet::Remove(void* key) { … } ALWAYS_INLINE LockFreeAddressHashSet::Node* LockFreeAddressHashSet::FindNode( void* key) const { … } // static ALWAYS_INLINE uint32_t LockFreeAddressHashSet::Hash(void* key) { … } } // namespace base #endif // BASE_SAMPLING_HEAP_PROFILER_LOCK_FREE_ADDRESS_HASH_SET_H_