src/hotspot/share/utilities/concurrentHashTable.inline.hpp
changeset 52717 b22da519f2e3
parent 52516 d5eebe1e03fe
child 53239 c024fcb88ede
--- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp	Wed Nov 28 11:06:58 2018 +0100
+++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp	Wed Nov 28 11:06:27 2018 +0100
@@ -876,8 +876,8 @@
 template <typename VALUE, typename CONFIG, MEMFLAGS F>
 template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
 inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
-  internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
-                  CALLBACK_FUNC& callback, bool* grow_hint, bool* clean_hint)
+  internal_get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
+                      CALLBACK_FUNC& callback_f, bool* grow_hint, bool* clean_hint)
 {
   bool ret = false;
   bool clean = false;
@@ -901,7 +901,7 @@
           new_node->set_next(first_at_start);
         }
         if (bucket->cas_first(new_node, first_at_start)) {
-          callback(true, new_node->value());
+          callback_f(true, new_node->value());
           new_node = NULL;
           ret = true;
           break; /* leave critical section */
@@ -910,7 +910,7 @@
         locked = bucket->is_locked();
       } else {
         // There is a duplicate.
-        callback(false, old->value());
+        callback_f(false, old->value());
         break; /* leave critical section */
       }
     } /* leave critical section */
@@ -946,6 +946,70 @@
 }
 
 template <typename VALUE, typename CONFIG, MEMFLAGS F>
+template <typename LOOKUP_FUNC>
+inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
+  internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
+                  bool* grow_hint, bool* clean_hint)
+{
+  bool ret = false;
+  bool clean = false;
+  bool locked;
+  size_t loops = 0;
+  size_t i = 0;
+  uintx hash = lookup_f.get_hash();
+  Node* new_node = Node::create_node(value, NULL);
+
+  while (true) {
+    {
+      ScopedCS cs(thread, this); /* protected the table/bucket */
+      Bucket* bucket = get_bucket(hash);
+      Node* first_at_start = bucket->first();
+      Node* old = get_node(bucket, lookup_f, &clean, &loops);
+      if (old == NULL) {
+        new_node->set_next(first_at_start);
+        if (bucket->cas_first(new_node, first_at_start)) {
+          new_node = NULL;
+          ret = true;
+          break; /* leave critical section */
+        }
+        // CAS failed we must leave critical section and retry.
+        locked = bucket->is_locked();
+      } else {
+        // There is a duplicate.
+        break; /* leave critical section */
+      }
+    } /* leave critical section */
+    i++;
+    if (locked) {
+      os::naked_yield();
+    } else {
+      SpinPause();
+    }
+  }
+
+  if (new_node != NULL) {
+    // CAS failed and a duplicate was inserted, we must free this node.
+    Node::destroy_node(new_node);
+  } else if (i == 0 && clean) {
+    // We only do cleaning on fast inserts.
+    Bucket* bucket = get_bucket_locked(thread, lookup_f.get_hash());
+    delete_in_bucket(thread, bucket, lookup_f);
+    bucket->unlock();
+    clean = false;
+  }
+
+  if (grow_hint != NULL) {
+    *grow_hint = loops > _grow_hint;
+  }
+
+  if (clean_hint != NULL) {
+    *clean_hint = clean;
+  }
+
+  return ret;
+}
+
+template <typename VALUE, typename CONFIG, MEMFLAGS F>
 template <typename FUNC>
 inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
   visit_nodes(Bucket* bucket, FUNC& visitor_f)