[armedbear-cvs] r12969 - trunk/abcl/src/org/armedbear/lisp

Erik Huelsmann ehuelsmann at common-lisp.net
Sat Oct 9 23:28:32 UTC 2010


Author: ehuelsmann
Date: Sat Oct  9 19:28:31 2010
New Revision: 12969

Log:
Implement nearly lock-free hash reader functionality, by
looking really well at ConcurrentHashMap - agreed.

Modified:
   trunk/abcl/src/org/armedbear/lisp/HashTable.java

Modified: trunk/abcl/src/org/armedbear/lisp/HashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/HashTable.java	(original)
+++ trunk/abcl/src/org/armedbear/lisp/HashTable.java	Sat Oct  9 19:28:31 2010
@@ -33,8 +33,7 @@
  */
 package org.armedbear.lisp;
 
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
 import static org.armedbear.lisp.Lisp.*;
 
 public abstract class HashTable extends LispObject {
@@ -46,15 +45,12 @@
     // of elements exceeds the threshold, the implementation calls rehash().
     protected int threshold;
     // Array containing the actual key-value mappings.
-    
     @SuppressWarnings("VolatileArrayField")
     protected volatile HashEntry[] buckets;
-    
     // The number of key-value pairs.
-    protected int count;
-    private int mask;
+    protected volatile int count;
     final Comparator comparator;
-    final private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+    final private ReentrantLock lock = new ReentrantLock();
 
     protected HashTable(Comparator c, int size, LispObject rehashSize,
             LispObject rehashThreshold) {
@@ -63,7 +59,6 @@
         buckets = new HashEntry[size];
         threshold = (int) (size * loadFactor);
         comparator = c;
-        mask = buckets.length - 1;
     }
 
     protected static int calculateInitialCapacity(int size) {
@@ -156,12 +151,12 @@
     }
 
     public void clear() {
-        lock.writeLock().lock();
+        lock.lock();
         try {
             buckets = new HashEntry[buckets.length];
             count = 0;
         } finally {
-            lock.writeLock().unlock();
+            lock.unlock();
         }
     }
 
@@ -233,8 +228,8 @@
     }
 
     protected HashEntry getEntry(LispObject key) {
-        int index = comparator.hash(key) & mask;
-        HashEntry e = buckets[index];
+        HashEntry[] b = buckets;
+        HashEntry e = b[comparator.hash(key) & (b.length - 1)];
         while (e != null) {
             if (comparator.keysEqual(key, e.key)) {
                 return e;
@@ -245,20 +240,26 @@
     }
 
     public LispObject get(LispObject key) {
-        lock.readLock().lock();
+        HashEntry e = getEntry(key);
+        LispObject v = (e == null) ? null : e.value;
+
+        if (e == null || v != null) {
+            return v;
+        }
+
+        lock.lock();
         try {
-            HashEntry e = getEntry(key);
-            return (e == null) ? null : e.value;
+            return e.value;
         } finally {
-            lock.readLock().unlock();
+            lock.unlock();
         }
     }
 
     public void put(LispObject key, LispObject value) {
-        lock.writeLock().lock();
+        lock.lock();
         try {
             HashEntry e = getEntry(key);
-            if (e == null) {
+            if (e != null) {
                 e.value = value;
             } else {
                 // Not found. We need to add a new entry.
@@ -266,18 +267,18 @@
                     rehash();
                 }
 
-                int index = comparator.hash(key) & mask;
+                int index = comparator.hash(key) & (buckets.length - 1);
                 buckets[index] = new HashEntry(key, value, buckets[index]);
             }
         } finally {
-            lock.writeLock().unlock();
+            lock.unlock();
         }
     }
 
     public LispObject remove(LispObject key) {
-        lock.writeLock().lock();
+        lock.lock();
         try {
-            int index = comparator.hash(key) & mask;
+            int index = comparator.hash(key) & (buckets.length - 1);
 
             HashEntry e = buckets[index];
             HashEntry last = null;
@@ -296,16 +297,16 @@
             }
             return null;
         } finally {
-            lock.writeLock().unlock();
+            lock.unlock();
         }
     }
 
     protected void rehash() {
-        lock.writeLock().lock();
+        lock.lock();
         try {
             final int newCapacity = buckets.length * 2;
             threshold = (int) (newCapacity * loadFactor);
-            mask = newCapacity - 1;
+            int mask = newCapacity - 1;
             HashEntry[] newBuckets = new HashEntry[newCapacity];
 
             for (int i = buckets.length; i-- > 0;) {
@@ -318,7 +319,7 @@
             }
             buckets = newBuckets;
         } finally {
-            lock.writeLock().unlock();
+            lock.unlock();
         }
     }
 
@@ -415,7 +416,7 @@
     protected static class HashEntry {
 
         LispObject key;
-        LispObject value;
+        volatile LispObject value;
         HashEntry next;
 
         HashEntry(LispObject key, LispObject value, HashEntry next) {




More information about the armedbear-cvs mailing list