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