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;
 
  585    ib::info info(ER_IB_MSG_LOCK_FREE_HASH_USAGE_STATS);
 
  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;
 
Kerberos Client Authentication nullptr
Definition: auth_kerberos_client_plugin.cc:247
 
The class info is used to emit informational log messages.
Definition: ut0log.h:189
 
Allocator that allows std::* containers to manage their memory through ut::malloc* and ut::free libra...
Definition: ut0new.h:2183
 
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
 
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
 
#define T
Definition: jit_executor_value.cc:373
 
uint counter
Definition: mysqlimport.cc:58
 
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
 
void print_stats()
Definition: profiling.h:227
 
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:199
 
void delete_(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new*() variants.
Definition: ut0new.h:811
 
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:2444
 
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:1652
 
T * new_arr(Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:961
 
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:378
 
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:105
 
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:93
 
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:200