34#ifndef ut0lock_free_hash_h
35#define ut0lock_free_hash_h
37#define BOOST_ATOMIC_NO_LIB
64 virtual int64_t
get(uint64_t
key)
const = 0;
70 virtual void set(uint64_t
key, int64_t val) = 0;
86#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
101 for (
size_t i = 0; i <
m_cnt.size(); i++) {
115 other.m_counter =
nullptr;
118 explicit operator bool() const noexcept {
return m_counter !=
nullptr; }
140 for (
size_t i = 0; i <
m_cnt.size(); i++) {
142 std::this_thread::yield();
154 cpu =
static_cast<size_t>(os_getcpu());
159 return cpu %
m_cnt.size();
171 std::array<ut::Cacheline_aligned<std::atomic<uint64_t>>, 256>
m_cnt;
189 ut_ad(n_elements > 0);
193 return ut::aligned_new_withkey<ut_lock_free_list_node_t<T>>(
213 next_t grow(int64_t deleted_val,
bool *grown_by_this_thread) {
230 next_t expected =
nullptr;
237 ut_ad(expected !=
nullptr);
239 *grown_by_this_thread =
false;
243 *grown_by_this_thread =
true;
303 const int64_t val =
m_base[i].m_val.load(std::memory_order_relaxed);
305 if (val == deleted_val) {
384#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
387 m_n_search_iterations(0)
390 ut_a(initial_size > 0);
414 }
while (arr !=
nullptr);
426 int64_t
get(uint64_t
key)
const override {
434 const auto tuple = handle_and_tuple.second;
436 if (tuple ==
nullptr) {
446 int64_t v = tuple->m_val.load(std::memory_order_relaxed);
474 void set(uint64_t
key, int64_t val)
override {
510 const auto tuple = handle_and_tuple.second;
512 if (tuple ==
nullptr) {
517 int64_t v = tuple->m_val.load(std::memory_order_relaxed);
524 if (tuple->m_val.compare_exchange_strong(v,
DELETED)) {
578#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
582 const ulint n_search = m_n_search;
583 const ulint n_search_iterations = m_n_search_iterations;
586 info <<
"Lock free hash usage stats: number of searches=" << n_search
587 <<
", number of search iterations=" << n_search_iterations;
589 info <<
"average iterations per search: "
590 << (double)n_search_iterations / n_search;
597 static const uint64_t
UNUSED = UINT64_MAX;
654 uint64_t
key)
const {
655#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
660 const size_t end =
start + arr_size;
662 for (
size_t i =
start; i <
end; i++) {
663#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
664 ++m_n_search_iterations;
668 const size_t cur_pos = i & (arr_size - 1);
672 const uint64_t cur_key = cur_tuple->
m_key.load(std::memory_order_relaxed);
674 if (cur_key ==
key) {
676 }
else if (cur_key ==
UNUSED || cur_key ==
AVOID) {
692 std::pair<ut_lock_free_cnt_t::handle_t, key_val_t *>
get_tuple(
695 auto handle = (*arr)->begin_access();
703 (*arr)->m_n_base_elements,
key);
706 return {std::move(
handle), t};
709 *arr = (*arr)->
m_next.load();
711 if (*arr ==
nullptr) {
728#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
733 const size_t end =
start + arr_size;
735 for (
size_t i =
start; i <
end; i++) {
736#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
737 ++m_n_search_iterations;
741 const size_t cur_pos = i & (arr_size - 1);
745 const uint64_t cur_key = cur_tuple->
m_key.load(std::memory_order_relaxed);
747 if (cur_key ==
key) {
752 uint64_t expected =
UNUSED;
753 if (cur_tuple->m_key.compare_exchange_strong(expected,
key)) {
761 if (expected ==
key) {
785 uint64_t k = t->
m_key.load(std::memory_order_relaxed);
792 int64_t v = t->
m_val.load(std::memory_order_relaxed);
853 int64_t cur_val = t->
m_val.load(std::memory_order_relaxed);
866 new_val = cur_val + val_to_set;
869 new_val = val_to_set;
872 if (t->
m_val.compare_exchange_strong(cur_val, new_val)) {
897 if (next ==
nullptr) {
914 ut_a(
m_data.compare_exchange_strong(expected, next));
950 arr_node_t *arr,
bool optimize_allowed =
true) {
951 bool call_optimize =
false;
980 if (next !=
nullptr) {
989 bool grown_by_this_thread;
993 if (grown_by_this_thread) {
994 call_optimize =
true;
998 if (optimize_allowed && call_optimize) {
1007 typedef std::list<arr_node_t *, hollow_alloc_t>
hollow_t;
1031#ifdef UT_HASH_IMPLEMENT_PRINT_STATS
1037 mutable std::atomic<uint64_t> m_n_search;
1040 mutable std::atomic<uint64_t> m_n_search_iterations;
The class info is used to emit informational log messages.
Definition: ut0log.h:188
Allocator that allows std::* containers to manage their memory through ut::malloc* and ut::free libra...
Definition: ut0new.h:2182
An interface class to a basic hash table, that ut_lock_free_hash_t is.
Definition: ut0lock_free_hash.h:52
static const int64_t NOT_FOUND
The value that is returned when the searched for key is not found.
Definition: ut0lock_free_hash.h:56
virtual void del(uint64_t key)=0
Delete a (key, val) pair from the hash.
virtual int64_t get(uint64_t key) const =0
Get the value mapped to a given key.
virtual void dec(uint64_t key)=0
Decrement the value of a given key with 1 or insert a new tuple (key, -1).
virtual void inc(uint64_t key)=0
Increment the value for a given key with 1 or insert a new tuple (key, 1).
virtual void set(uint64_t key, int64_t val)=0
Set the value for a given key, either inserting a new (key, val) tuple or overwriting an existent val...
virtual ~ut_hash_interface_t()=default
Destructor.
Definition: ut0lock_free_hash.h:106
handle_t(handle_t &&other) noexcept
Definition: ut0lock_free_hash.h:114
std::atomic< uint64_t > * m_counter
Definition: ut0lock_free_hash.h:127
handle_t(std::atomic< uint64_t > *counter)
Definition: ut0lock_free_hash.h:110
~handle_t()
Definition: ut0lock_free_hash.h:120
handle_t()
Definition: ut0lock_free_hash.h:108
Lock free ref counter.
Definition: ut0lock_free_hash.h:95
ut_lock_free_cnt_t()
Constructor.
Definition: ut0lock_free_hash.h:98
size_t n_cnt_index() const
Derive an appropriate index in m_cnt[] for the current thread.
Definition: ut0lock_free_hash.h:150
handle_t reference()
Increment the counter.
Definition: ut0lock_free_hash.h:131
void await_release_of_old_references() const
Wait until all previously existing references get released.
Definition: ut0lock_free_hash.h:139
std::array< ut::Cacheline_aligned< std::atomic< uint64_t > >, 256 > m_cnt
The shards of the counter.
Definition: ut0lock_free_hash.h:171
Lock free hash table.
Definition: ut0lock_free_hash.h:374
void set(uint64_t key, int64_t val) override
Set the value for a given key, either inserting a new (key, val) tuple or overwriting an existent val...
Definition: ut0lock_free_hash.h:474
static const int64_t DELETED
A val == DELETED designates that this cell in the array has been used in the past,...
Definition: ut0lock_free_hash.h:609
void inc(uint64_t key) override
Increment the value for a given key with 1 or insert a new tuple (key, 1).
Definition: ut0lock_free_hash.h:557
bool update_tuple(key_val_t *t, int64_t val_to_set, bool is_delta)
Update the value of a given tuple.
Definition: ut0lock_free_hash.h:852
bool m_del_when_zero
True if a tuple should be automatically deleted from the hash if its value becomes 0 after an increme...
Definition: ut0lock_free_hash.h:1029
static const uint64_t UNUSED
A key == UNUSED designates that this cell in the array is empty.
Definition: ut0lock_free_hash.h:597
size_t guess_position(uint64_t key, size_t arr_size) const
A hash function used to map a key to its suggested position in the array.
Definition: ut0lock_free_hash.h:639
ut_lock_free_list_node_t< key_val_t > arr_node_t
An array node in the hash.
Definition: ut0lock_free_hash.h:629
void optimize()
Optimize the hash table.
Definition: ut0lock_free_hash.h:889
void insert_or_update(uint64_t key, int64_t val, bool is_delta, arr_node_t *arr, bool optimize_allowed=true)
Insert a new tuple or update an existent one.
Definition: ut0lock_free_hash.h:949
ib_mutex_t m_optimize_latch
Concurrent copy-all-elements-to-the-next-array, removal of the head of the list and freeing of its m_...
Definition: ut0lock_free_hash.h:1025
void dec(uint64_t key) override
Decrement the value of a given key with 1 or insert a new tuple (key, -1).
Definition: ut0lock_free_hash.h:571
std::pair< ut_lock_free_cnt_t::handle_t, key_val_t * > get_tuple(uint64_t key, arr_node_t **arr) const
Get the array cell of a key.
Definition: ut0lock_free_hash.h:692
static const uint64_t AVOID
A key == AVOID designates an unusable cell.
Definition: ut0lock_free_hash.h:604
key_val_t * insert_or_get_position_in_array(key_val_t *arr, size_t arr_size, uint64_t key)
Insert the given key into a given array or return its cell if already present.
Definition: ut0lock_free_hash.h:726
std::list< arr_node_t *, hollow_alloc_t > hollow_t
Definition: ut0lock_free_hash.h:1007
void del(uint64_t key) override
Delete a (key, val) pair from the hash.
Definition: ut0lock_free_hash.h:502
key_val_t * get_tuple_from_array(key_val_t *arr, size_t arr_size, uint64_t key) const
Get the array cell of a key from a given array.
Definition: ut0lock_free_hash.h:653
int64_t get(uint64_t key) const override
Get the value mapped to a given key.
Definition: ut0lock_free_hash.h:426
hollow_t * m_hollow_objects
Container for hollow (semi-destroyed) objects that have been removed from the list that starts at m_d...
Definition: ut0lock_free_hash.h:1015
void copy_to_another_array(arr_node_t *src_arr, arr_node_t *dst_arr)
Copy all used elements from one array to another.
Definition: ut0lock_free_hash.h:781
ut::allocator< arr_node_t * > hollow_alloc_t
Definition: ut0lock_free_hash.h:1006
ut_lock_free_hash_t(size_t initial_size, bool del_when_zero)
Constructor.
Definition: ut0lock_free_hash.h:382
static const int64_t GOTO_NEXT_ARRAY
A val == GOTO_NEXT_ARRAY designates that this tuple (key, whatever) has been moved to the next array.
Definition: ut0lock_free_hash.h:614
~ut_lock_free_hash_t() override
Destructor.
Definition: ut0lock_free_hash.h:403
std::atomic< arr_node_t * > m_data
Storage for the (key, val) tuples.
Definition: ut0lock_free_hash.h:1004
A node in a linked list of arrays.
Definition: ut0lock_free_hash.h:177
static ut_lock_free_list_node_t * alloc(size_t n_elements)
Definition: ut0lock_free_hash.h:192
std::atomic< next_t > m_next
Pointer to the next node if any or NULL.
Definition: ut0lock_free_hash.h:291
size_t n_deleted(int64_t deleted_val) const
Count the number of deleted elements.
Definition: ut0lock_free_hash.h:299
ut_lock_free_list_node_t< T > * next_t
Definition: ut0lock_free_hash.h:179
ut_lock_free_cnt_t m_n_ref
Counter for the current number of readers and writers to this object.
Definition: ut0lock_free_hash.h:317
std::atomic_bool m_pending_free
Indicate whether some thread is waiting for readers to go away before it can free the memory occupied...
Definition: ut0lock_free_hash.h:286
next_t grow(int64_t deleted_val, bool *grown_by_this_thread)
Create and append a new array to this one and store a pointer to it in 'm_next'.
Definition: ut0lock_free_hash.h:213
ut_lock_free_cnt_t::handle_t begin_access()
Mark the beginning of an access to this object.
Definition: ut0lock_free_hash.h:259
size_t m_n_base_elements
Number of elements in 'm_base'.
Definition: ut0lock_free_hash.h:282
static void dealloc(ut_lock_free_list_node_t *ptr)
Definition: ut0lock_free_hash.h:198
ut_lock_free_list_node_t(size_t n_elements)
Constructor.
Definition: ut0lock_free_hash.h:183
ut::unique_ptr< T[]> m_base
Base array.
Definition: ut0lock_free_hash.h:279
void await_release_of_old_references()
Wait until all previously held references are released.
Definition: ut0lock_free_hash.h:274
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:222
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:177
uint counter
Definition: mysqlimport.cc:54
std::string print_stats(::recovery_statistics const &internal_stats, ::recovery_statistics const &external_stats)
Composes a string presenting the statistics for the given objects.
Definition: recovery.cc:365
bool load(THD *, const dd::String_type &fname, dd::String_type *buf)
Read an sdi file from disk and store in a buffer.
Definition: sdi_file.cc:308
Unique_ptr< T, std::nullptr_t > make_unique(size_t size)
In-place constructs a new unique pointer with no specific allocator and with array type T.
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
static int handle(int sql_errno, const char *sqlstate, const char *message, void *state)
Bridge function between the C++ API offered by this module and the C API of the parser service.
Definition: services.cc:64
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
const thread_local size_t this_thread_hash
The hash value of the current thread's id.
Definition: os0thread.h:74
static uint64_t hash_uint64(uint64_t value)
Hashes a 64-bit integer.
Definition: ut0rnd.h:189
void delete_(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new*() variants.
Definition: ut0new.h:810
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2439
PSI_memory_key_t make_psi_memory_key(PSI_memory_key key)
Convenience helper function to create type-safe representation of PSI_memory_key.
Definition: ut0new.h:190
void aligned_delete(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_*() variants.
Definition: ut0new.h:1651
T * new_arr(Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:960
NUMA API wrapper over various operating system specific APIs.
The interface to the operating system process and thread control primitives.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
(key, val) tuple type.
Definition: ut0lock_free_hash.h:617
key_val_t()
Definition: ut0lock_free_hash.h:618
std::atomic< int64_t > m_val
Value.
Definition: ut0lock_free_hash.h:624
std::atomic< uint64_t > m_key
Key.
Definition: ut0lock_free_hash.h:621
@ LATCH_ID_LOCK_FREE_HASH
Definition: sync0types.h:375
Version control for database, common definitions, and include files.
unsigned long int ulint
Definition: univ.i:406
Utilities related to CPU cache.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:69
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:57
void mutex_destroy(Mutex *mutex)
Removes a mutex instance from the mutex list.
Definition: ut0mutex.h:248
#define mutex_exit(M)
Definition: ut0mutex.h:123
#define mutex_enter(M)
Definition: ut0mutex.h:117
#define mutex_create(I, M)
Definition: ut0mutex.h:110
Dynamic memory allocation routines and custom allocators specifically crafted to support memory instr...
PSI_memory_key mem_key_ut_lock_free_hash_t
Definition: ut0new.cc:65
Random numbers and hashing.
#define ut_is_2pow(n)
Determines if a number is zero or a power of two.
Definition: ut0ut.h:197