src/hotspot/share/utilities/concurrentHashTable.hpp
author rehn
Wed, 28 Nov 2018 11:06:27 +0100
changeset 52717 b22da519f2e3
parent 52516 d5eebe1e03fe
child 53149 259c36ef27df
permissions -rw-r--r--
8213791: StringTable: Use get and insert Reviewed-by: eosterlund, gziemski
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     1
/*
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     2
 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     4
 *
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     7
 * published by the Free Software Foundation.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     8
 *
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    13
 * accompanied this code).
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    14
 *
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    18
 *
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    21
 * questions.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    22
 *
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    23
 */
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    24
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    25
#ifndef SHARE_UTILITIES_CONCURRENT_HASH_TABLE_HPP
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    26
#define SHARE_UTILITIES_CONCURRENT_HASH_TABLE_HPP
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    27
52332
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51405
diff changeset
    28
#include "memory/allocation.hpp"
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51405
diff changeset
    29
#include "utilities/globalCounter.hpp"
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51405
diff changeset
    30
#include "utilities/globalDefinitions.hpp"
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51405
diff changeset
    31
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    32
// A mostly concurrent-hash-table where the read-side is wait-free, inserts are
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    33
// CAS and deletes mutual exclude each other on per bucket-basis. VALUE is the
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    34
// type kept inside each Node and CONFIG contains hash and allocation methods.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    35
// A CALLBACK_FUNC and LOOKUP_FUNC needs to be provided for get and insert.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    36
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    37
class Thread;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    38
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    39
template <typename VALUE, typename CONFIG, MEMFLAGS F>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    40
class ConcurrentHashTable : public CHeapObj<F> {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    41
 private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    42
  // This is the internal node structure.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    43
  // Only constructed with placement new from memory allocated with MEMFLAGS of
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    44
  // the InternalTable or user-defined memory.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    45
  class Node {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    46
   private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    47
    Node * volatile _next;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    48
    VALUE _value;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    49
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    50
    Node(const VALUE& value, Node* next = NULL)
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    51
      : _next(next), _value(value) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    52
      assert((((uintptr_t)this) & ((uintptr_t)0x3)) == 0,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    53
             "Must 16 bit aligned.");
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    54
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    55
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    56
    Node* next() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    57
    void set_next(Node* node)         { _next = node; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    58
    Node* const volatile * next_ptr() { return &_next; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    59
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    60
    VALUE* value()                    { return &_value; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    61
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    62
    // Creates a node.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    63
    static Node* create_node(const VALUE& value, Node* next = NULL) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    64
      return new (CONFIG::allocate_node(sizeof(Node), value)) Node(value, next);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    65
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    66
    // Destroys a node.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    67
    static void destroy_node(Node* node) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    68
      CONFIG::free_node((void*)node, node->_value);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    69
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    70
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    71
    void print_on(outputStream* st) const {};
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    72
    void print_value_on(outputStream* st) const {};
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    73
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    74
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    75
  // Only constructed with placement new[] from an array allocated with MEMFLAGS
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    76
  // of InternalTable.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    77
  class Bucket {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    78
   private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    79
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    80
    // Embedded state in two low bits in first pointer is a spinlock with 3
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    81
    // states, unlocked, locked, redirect. You must never busy-spin on trylock()
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    82
    // or call lock() without _resize_lock, that would deadlock. Redirect can
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    83
    // only be installed by owner and is the final state of a bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    84
    // The only two valid flows are:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    85
    // unlocked -> locked -> unlocked
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    86
    // unlocked -> locked -> redirect
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    87
    // Locked state only applies to an updater.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    88
    // Reader only check for redirect.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    89
    Node * volatile _first;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    90
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    91
    static const uintptr_t STATE_LOCK_BIT     = 0x1;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    92
    static const uintptr_t STATE_REDIRECT_BIT = 0x2;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    93
    static const uintptr_t STATE_MASK         = 0x3;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    94
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    95
    // Get the first pointer unmasked.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    96
    Node* first_raw() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    97
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    98
    // Methods to manipulate the embedded.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
    99
    static bool is_state(Node* node, uintptr_t bits) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   100
      return (bits & (uintptr_t)node) == bits;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   101
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   102
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   103
    static Node* set_state(Node* n, uintptr_t bits) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   104
      return (Node*)(bits | (uintptr_t)n);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   105
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   106
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   107
    static uintptr_t get_state(Node* node) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   108
      return (((uintptr_t)node) & STATE_MASK);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   109
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   110
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   111
    static Node* clear_state(Node* node) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   112
      return (Node*)(((uintptr_t)node) & (~(STATE_MASK)));
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   113
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   114
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   115
    static Node* clear_set_state(Node* node, Node* state) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   116
      return (Node*)(((uintptr_t)clear_state(node)) ^ get_state(state));
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   117
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   118
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   119
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   120
    // A bucket is only one pointer with the embedded state.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   121
    Bucket() : _first(NULL) {};
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   122
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   123
    // Get the first pointer unmasked.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   124
    Node* first() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   125
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   126
    // Get a pointer to the const first pointer. Do not deference this
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   127
    // pointer, the pointer pointed to _may_ contain an embedded state. Such
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   128
    // pointer should only be used as input to release_assign_node_ptr.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   129
    Node* const volatile * first_ptr() { return &_first; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   130
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   131
    // This is the only place where a pointer to a Node pointer that potentially
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   132
    // is _first should be changed. Otherwise we destroy the embedded state. We
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   133
    // only give out pointer to const Node pointer to avoid accidental
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   134
    // assignment, thus here we must cast const part away. Method is not static
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   135
    // due to an assert.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   136
    void release_assign_node_ptr(Node* const volatile * dst, Node* node) const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   137
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   138
    // This method assigns this buckets last Node next ptr to input Node.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   139
    void release_assign_last_node_next(Node* node);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   140
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   141
    // Setting the first pointer must be done with CAS.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   142
    bool cas_first(Node *node, Node* expect);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   143
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   144
    // Returns true if this bucket is redirecting to a new table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   145
    // Redirect is a terminal state and will never change.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   146
    bool have_redirect() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   147
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   148
    // Return true if this bucket is locked for updates.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   149
    bool is_locked() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   150
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   151
    // Return true if this bucket was locked.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   152
    bool trylock();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   153
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   154
    // The bucket might be invalid, due to a concurrent resize. The lock()
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   155
    // method do no respect that and can deadlock if caller do not hold
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   156
    // _resize_lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   157
    void lock();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   159
    // Unlocks this bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   160
    void unlock();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   161
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   162
    // Installs redirect in this bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   163
    // Prior to doing so you must have successfully locked this bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   164
    void redirect();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   165
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   166
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   167
  // The backing storage table holding the buckets and it's size and mask-bits.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   168
  // Table is always a power of two for two reasons:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   169
  // - Re-size can only change the size into half or double
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   170
  //   (any pow 2 would also be possible).
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   171
  // - Use masking of hash for bucket index.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   172
  class InternalTable : public CHeapObj<F> {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   173
   private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   174
    Bucket* _buckets;        // Bucket array.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   175
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   176
    const size_t _log2_size; // Size in log2.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   177
    const size_t _size;      // Size in log10.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   178
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   179
    // The mask used on hash for selecting bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   180
    // The masked value is guaranteed be to inside the buckets array.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   181
    const size_t _hash_mask;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   182
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   183
    // Create a backing table
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   184
    InternalTable(size_t log2_size);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   185
    ~InternalTable();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   186
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   187
    Bucket* get_buckets() { return _buckets; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   188
    Bucket* get_bucket(size_t idx) { return &_buckets[idx]; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   189
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   190
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   191
  // Used as default functor when no functor supplied for some methods.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   192
  struct NoOp {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   193
    void operator()(VALUE*) {}
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   194
    const VALUE& operator()() {}
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   195
    void operator()(bool, VALUE*) {}
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   196
  } noOp;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   197
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   198
  // For materializing a supplied value.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   199
  class LazyValueRetrieve {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   200
   private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   201
    const VALUE& _val;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   202
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   203
    LazyValueRetrieve(const VALUE& val) : _val(val) {}
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   204
    const VALUE& operator()() { return _val; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   205
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   206
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   207
  InternalTable* _table;      // Active table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   208
  InternalTable* _new_table;  // Table we are resizing to.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   209
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   210
  // Default sizes
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   211
  static const size_t DEFAULT_MAX_SIZE_LOG2 = 21;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   212
  static const size_t DEFAULT_START_SIZE_LOG2 = 13;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   213
  static const size_t DEFAULT_GROW_HINT = 4; // Chain length
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   214
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   215
  const size_t _log2_size_limit;  // The biggest size.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   216
  const size_t _log2_start_size;  // Start size.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   217
  const size_t _grow_hint;        // Number of linked items
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   218
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   219
  volatile bool _size_limit_reached;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   220
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   221
  // We serialize resizers and other bulk operations which do not support
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   222
  // concurrent resize with this lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   223
  Mutex* _resize_lock;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   224
  // Since we need to drop mutex for safepoints, but stop other threads from
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   225
  // taking the mutex after a safepoint this bool is the actual state. After
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   226
  // acquiring the mutex you must check if this is already locked. If so you
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   227
  // must drop the mutex until the real lock holder grabs the mutex.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   228
  volatile Thread* _resize_lock_owner;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   229
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   230
  // Return true if lock mutex/state succeeded.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   231
  bool try_resize_lock(Thread* locker);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   232
  // Returns when both mutex and state are proper locked.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   233
  void lock_resize_lock(Thread* locker);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   234
  // Unlocks mutex and state.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   235
  void unlock_resize_lock(Thread* locker);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   236
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   237
  // This method sets the _invisible_epoch and do a write_synchronize.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   238
  // Subsequent calls check the state of _invisible_epoch and determine if the
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   239
  // write_synchronize can be avoided. If not, it sets the _invisible_epoch
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   240
  // again and do a write_synchronize.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   241
  void write_synchonize_on_visible_epoch(Thread* thread);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   242
  // To be-able to avoid write_synchronize in resize and other bulk operation,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   243
  // this field keep tracks if a version of the hash-table was ever been seen.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   244
  // We the working thread pointer as tag for debugging. The _invisible_epoch
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   245
  // can only be used by the owner of _resize_lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   246
  volatile Thread* _invisible_epoch;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   247
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   248
  // Scoped critical section, which also handles the invisible epochs.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   249
  // An invisible epoch/version do not need a write_synchronize().
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   250
  class ScopedCS: public StackObj {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   251
   protected:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   252
    Thread* _thread;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   253
    ConcurrentHashTable<VALUE, CONFIG, F>* _cht;
52332
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51405
diff changeset
   254
    GlobalCounter::CSContext _cs_context;
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   255
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   256
    ScopedCS(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* cht);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   257
    ~ScopedCS();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   258
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   259
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   260
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   261
  // Max number of deletes in one bucket chain during bulk delete.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   262
  static const size_t BULK_DELETE_LIMIT = 256;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   263
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   264
  // Simple getters and setters for the internal table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   265
  InternalTable* get_table() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   266
  InternalTable* get_new_table() const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   267
  InternalTable* set_table_from_new();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   268
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   269
  // Destroys all nodes.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   270
  void free_nodes();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   271
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   272
  // Mask away high bits of hash.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   273
  static size_t bucket_idx_hash(InternalTable* table, const uintx hash) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   274
    return ((size_t)hash) & table->_hash_mask;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   275
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   276
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   277
  // Returns bucket for hash for that internal table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   278
  Bucket* get_bucket_in(InternalTable* table, const uintx hash) const {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   279
    size_t bucket_index = bucket_idx_hash(table, hash);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   280
    return table->get_bucket(bucket_index);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   281
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   282
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   283
  // Return correct bucket for reading and handles resizing.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   284
  Bucket* get_bucket(const uintx hash) const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   285
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   286
  // Return correct bucket for updates and handles resizing.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   287
  Bucket* get_bucket_locked(Thread* thread, const uintx hash);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   288
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   289
  // Finds a node.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   290
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   291
  Node* get_node(const Bucket* const bucket, LOOKUP_FUNC& lookup_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   292
                 bool* have_dead, size_t* loops = NULL) const;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   293
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   294
  // Method for shrinking.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   295
  bool internal_shrink_prolog(Thread* thread, size_t log2_size);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   296
  void internal_shrink_epilog(Thread* thread);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   297
  void internal_shrink_range(Thread* thread, size_t start, size_t stop);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   298
  bool internal_shrink(Thread* thread, size_t size_limit_log2);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   299
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   300
  // Methods for growing.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   301
  bool unzip_bucket(Thread* thread, InternalTable* old_table,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   302
                    InternalTable* new_table, size_t even_index,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   303
                    size_t odd_index);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   304
  bool internal_grow_prolog(Thread* thread, size_t log2_size);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   305
  void internal_grow_epilog(Thread* thread);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   306
  void internal_grow_range(Thread* thread, size_t start, size_t stop);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   307
  bool internal_grow(Thread* thread, size_t log2_size);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   308
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   309
  // Get a value.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   310
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   311
  VALUE* internal_get(Thread* thread, LOOKUP_FUNC& lookup_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   312
                      bool* grow_hint = NULL);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   313
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   314
  // Insert which handles a number of cases.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   315
  template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
52717
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   316
  bool internal_get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   317
                           CALLBACK_FUNC& callback_f, bool* grow_hint = NULL, bool* clean_hint = NULL);
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   318
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   319
  // Plain insert.
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   320
  template <typename LOOKUP_FUNC>
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   321
  bool internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   322
                       bool* grow_hint, bool* clean_hint);
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   323
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   324
  // Returns true if an item matching LOOKUP_FUNC is removed.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   325
  // Calls DELETE_FUNC before destroying the node.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   326
  template <typename LOOKUP_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   327
  bool internal_remove(Thread* thread, LOOKUP_FUNC& lookup_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   328
                       DELETE_FUNC& delete_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   329
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   330
  // Visits nodes with FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   331
  template <typename FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   332
  static bool visit_nodes(Bucket* bucket, FUNC& visitor_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   333
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   334
  // During shrink/grow we cannot guarantee that we only visit nodes once, with
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   335
  // current algorithm. To keep it simple caller will have locked
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   336
  // _resize_lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   337
  template <typename FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   338
  void do_scan_locked(Thread* thread, FUNC& scan_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   339
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   340
  // Check for dead items in a bucket.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   341
  template <typename EVALUATE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   342
  size_t delete_check_nodes(Bucket* bucket, EVALUATE_FUNC& eval_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   343
                            size_t num_del, Node** ndel);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   344
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   345
  // Check for dead items in this table. During shrink/grow we cannot guarantee
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   346
  // that we only visit nodes once. To keep it simple caller will have locked
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   347
  // _resize_lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   348
  template <typename EVALUATE_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   349
  void do_bulk_delete_locked(Thread* thread, EVALUATE_FUNC& eval_f
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   350
                             , DELETE_FUNC& del_f) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   351
    do_bulk_delete_locked_for(thread, 0, _table->_size, eval_f, del_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   352
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   353
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   354
  // To have prefetching for a VALUE that is pointer during
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   355
  // do_bulk_delete_locked, we have this helper classes. One for non-pointer
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   356
  // case without prefect and one for pointer with prefect.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   357
  template <bool b, typename EVALUATE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   358
  struct HaveDeletables {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   359
    static bool have_deletable(Bucket* bucket, EVALUATE_FUNC& eval_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   360
                               Bucket* prefetch_bucket);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   361
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   362
  template<typename EVALUATE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   363
  struct HaveDeletables<true, EVALUATE_FUNC> {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   364
    static bool have_deletable(Bucket* bucket, EVALUATE_FUNC& eval_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   365
                               Bucket* prefetch_bucket);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   366
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   367
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   368
  // Check for dead items in this table with range. During shrink/grow we cannot
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   369
  // guarantee that we only visit nodes once. To keep it simple caller will
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   370
  // have locked _resize_lock.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   371
  template <typename EVALUATE_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   372
  void do_bulk_delete_locked_for(Thread* thread, size_t start_idx,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   373
                                 size_t stop_idx, EVALUATE_FUNC& eval_f,
50608
1609a43e77ae 8204857: ConcurrentHashTable: Fix parallel processing
rehn
parents: 50445
diff changeset
   374
                                 DELETE_FUNC& del_f, bool is_mt = false);
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   375
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   376
  // Method to delete one items.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   377
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   378
  void delete_in_bucket(Thread* thread, Bucket* bucket, LOOKUP_FUNC& lookup_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   379
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   380
 public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   381
  ConcurrentHashTable(size_t log2size = DEFAULT_START_SIZE_LOG2,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   382
                      size_t log2size_limit = DEFAULT_MAX_SIZE_LOG2,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   383
                      size_t grow_hint = DEFAULT_GROW_HINT);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   384
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   385
  ~ConcurrentHashTable();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   386
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   387
  size_t get_size_log2(Thread* thread);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   388
  size_t get_node_size() const { return sizeof(Node); }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   389
  bool is_max_size_reached() { return _size_limit_reached; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   390
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   391
  // This means no paused bucket resize operation is going to resume
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   392
  // on this table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   393
  bool is_safepoint_safe() { return _resize_lock_owner == NULL; }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   394
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   395
  // Re-size operations.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   396
  bool shrink(Thread* thread, size_t size_limit_log2 = 0);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   397
  bool grow(Thread* thread, size_t size_limit_log2 = 0);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   398
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   399
  // All callbacks for get are under critical sections. Other callbacks may be
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   400
  // under critical section or may have locked parts of table. Calling any
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   401
  // methods on the table during a callback is not supported.Only MultiGetHandle
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   402
  // supports multiple gets.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   403
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   404
  // LOOKUP_FUNC is matching methods, VALUE_FUNC creates value to be inserted
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   405
  // and CALLBACK_FUNC is called with new or old value. Returns true if the
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   406
  // value already exists.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   407
  template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   408
  bool get_insert_lazy(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& val_f,
51405
8b23aa7cef47 8195100: Use a low latency hashtable for SymbolTable
gziemski
parents: 50608
diff changeset
   409
                       CALLBACK_FUNC& callback_f, bool* grow_hint = NULL, bool* clean_hint = NULL) {
52717
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   410
    return !internal_get_insert(thread, lookup_f, val_f, callback_f, grow_hint, clean_hint);
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   411
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   412
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   413
  // Same without CALLBACK_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   414
  template <typename LOOKUP_FUNC, typename VALUE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   415
  bool get_insert_lazy(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& val_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   416
                       bool* grow_hint = NULL) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   417
    return get_insert_lazy(thread, lookup_f, val_f, noOp, grow_hint);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   418
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   419
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   420
  // Same without VALUE_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   421
  template <typename LOOKUP_FUNC, typename CALLBACK_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   422
  bool get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   423
                  CALLBACK_FUNC& callback_f, bool* grow_hint = NULL) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   424
    LazyValueRetrieve vp(value);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   425
    return get_insert_lazy(thread, lookup_f, vp, callback_f, grow_hint);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   426
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   427
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   428
  // Same without CALLBACK_FUNC and VALUE_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   429
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   430
  bool get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   431
                  bool* grow_hint = NULL) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   432
    return get_insert(thread, lookup_f, value, noOp, grow_hint);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   433
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   434
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   435
  // Get methods return true on found item with LOOKUP_FUNC and FOUND_FUNC is
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   436
  // called.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   437
  template <typename LOOKUP_FUNC, typename FOUND_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   438
  bool get(Thread* thread, LOOKUP_FUNC& lookup_f, FOUND_FUNC& foundf,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   439
           bool* grow_hint = NULL);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   440
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   441
  // Return a copy of an item found with LOOKUP_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   442
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   443
  VALUE get_copy(Thread* thread, LOOKUP_FUNC& lookup_f, bool* grow_hint = NULL);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   444
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   445
  // Returns true true if the item was inserted, duplicates are found with
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   446
  // LOOKUP_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   447
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   448
  bool insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
51405
8b23aa7cef47 8195100: Use a low latency hashtable for SymbolTable
gziemski
parents: 50608
diff changeset
   449
              bool* grow_hint = NULL, bool* clean_hint = NULL) {
52717
b22da519f2e3 8213791: StringTable: Use get and insert
rehn
parents: 52516
diff changeset
   450
    return internal_insert(thread, lookup_f, value, grow_hint, clean_hint);
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   451
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   452
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   453
  // This does a fast unsafe insert and can thus only be used when there is no
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   454
  // risk for a duplicates and no other threads uses this table.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   455
  bool unsafe_insert(const VALUE& value);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   456
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   457
  // Returns true if items was deleted matching LOOKUP_FUNC and
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   458
  // prior to destruction DELETE_FUNC is called.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   459
  template <typename LOOKUP_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   460
  bool remove(Thread* thread, LOOKUP_FUNC& lookup_f, DELETE_FUNC& del_f) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   461
    return internal_remove(thread, lookup_f, del_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   462
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   463
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   464
  // Same without DELETE_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   465
  template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   466
  bool remove(Thread* thread, LOOKUP_FUNC& lookup_f) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   467
    return internal_remove(thread, lookup_f, noOp);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   468
  }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   469
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   470
  // Visit all items with SCAN_FUNC if no concurrent resize. Takes the resize
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   471
  // lock to avoid concurrent resizes. Else returns false.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   472
  template <typename SCAN_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   473
  bool try_scan(Thread* thread, SCAN_FUNC& scan_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   474
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   475
  // Visit all items with SCAN_FUNC when the resize lock is obtained.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   476
  template <typename SCAN_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   477
  void do_scan(Thread* thread, SCAN_FUNC& scan_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   478
52516
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   479
  // Visit all items with SCAN_FUNC without any protection.
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   480
  // It will assume there is no other thread accessing this
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   481
  // table during the safepoint. Must be called with VM thread.
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   482
  template <typename SCAN_FUNC>
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   483
  void do_safepoint_scan(SCAN_FUNC& scan_f);
d5eebe1e03fe 8213574: Deadlock in string table expansion when dumping lots of CDS classes
rehn
parents: 52332
diff changeset
   484
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   485
  // Destroying items matching EVALUATE_FUNC, before destroying items
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   486
  // DELETE_FUNC is called, if resize lock is obtained. Else returns false.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   487
  template <typename EVALUATE_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   488
  bool try_bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   489
                       DELETE_FUNC& del_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   490
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   491
  // Destroying items matching EVALUATE_FUNC, before destroying items
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   492
  // DELETE_FUNC is called, when the resize lock is successfully obtained.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   493
  template <typename EVALUATE_FUNC, typename DELETE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   494
  void bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   495
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   496
  // Writes statistics to the outputStream. Item sizes are calculated with
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   497
  // VALUE_SIZE_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   498
  template <typename VALUE_SIZE_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   499
  void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st,
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   500
                     const char* table_name);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   501
50445
bd6b78feb6a3 8195097: Make it possible to process StringTable outside safepoint
rehn
parents: 50158
diff changeset
   502
  // Moves all nodes from this table to to_cht
bd6b78feb6a3 8195097: Make it possible to process StringTable outside safepoint
rehn
parents: 50158
diff changeset
   503
  bool try_move_nodes_to(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* to_cht);
bd6b78feb6a3 8195097: Make it possible to process StringTable outside safepoint
rehn
parents: 50158
diff changeset
   504
50158
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   505
  // This is a Curiously Recurring Template Pattern (CRPT) interface for the
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   506
  // specialization.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   507
  struct BaseConfig {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   508
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   509
    // Called when the hash table needs the hash for a VALUE.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   510
    static uintx get_hash(const VALUE& value, bool* dead) {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   511
      return CONFIG::get_hash(value, dead);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   512
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   513
    // On get_copy if no value is found then this value is returned.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   514
    static const VALUE& notfound() {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   515
      return CONFIG::notfound();
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   516
    }
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   517
    // Default node allocation.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   518
    static void* allocate_node(size_t size, const VALUE& value);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   519
    // Default node reclamation.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   520
    static void free_node(void* memory, const VALUE& value);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   521
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   522
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   523
  // Scoped multi getter.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   524
  class MultiGetHandle : private ScopedCS {
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   525
   public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   526
    MultiGetHandle(Thread* thread, ConcurrentHashTable<VALUE, CONFIG, F>* cht)
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   527
      : ScopedCS(thread, cht) {}
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   528
    // In the MultiGetHandle scope you can lookup items matching LOOKUP_FUNC.
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   529
    // The VALUEs are safe as long as you never save the VALUEs outside the
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   530
    // scope, e.g. after ~MultiGetHandle().
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   531
    template <typename LOOKUP_FUNC>
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   532
    VALUE* get(LOOKUP_FUNC& lookup_f, bool* grow_hint = NULL);
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   533
  };
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   534
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   535
 private:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   536
  class BucketsOperation;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   537
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   538
 public:
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   539
  class BulkDeleteTask;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   540
  class GrowTask;
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   541
};
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   542
8e4fcfb4cfe4 8195098: Low latency hashtable for read-mostly scenarios
rehn
parents:
diff changeset
   543
#endif // include guard