Switch to using StampedLock 55/46355/1
authorRobert Varga <rovarga@cisco.com>
Fri, 9 Sep 2016 20:30:20 +0000 (22:30 +0200)
committerRobert Varga <rovarga@cisco.com>
Mon, 3 Oct 2016 11:35:44 +0000 (13:35 +0200)
Instead of using ReentrantReadWriteLock, use StampedLock,
which has better performance.

Change-Id: Ifb8c3c90fb05a37264e006acc7d94b4bde5d2893
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit 24f1985c8a8f8aa4afaafc2cec7a1908890c993a)

dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractRegistrationTree.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/AbstractRegistrationTreeTest.java

index 9da8f18cfa7ff4bf12e0542d30b0fa4193e67e52..c98826d6b23a3a8239972c10998804e8b9c118cd 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.mdsal.dom.spi;
 
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.StampedLock;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 
@@ -18,18 +18,22 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
  * @param <T> Type of registered object
  */
 public abstract class AbstractRegistrationTree<T> {
-    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
     private final RegistrationTreeNode<T> rootNode = new RegistrationTreeNode<>(null, null);
+    private final Lock writeLock;
+    private final Lock readLock;
 
     protected AbstractRegistrationTree() {
-
+        final StampedLock lock = new StampedLock();
+        readLock = lock.asReadLock();
+        writeLock = lock.asWriteLock();
     }
 
     /**
-     * Acquire the read-write lock. This should be done before invoking {@link #findNodeFor(Iterable)}.
+     * Acquire the read-write lock. This should be done before invoking {@link #findNodeFor(Iterable)}. This method
+     * must not be called when the lock is already held by this thread.
      */
     protected final void takeLock() {
-        rwLock.writeLock().lock();
+        writeLock.lock();
     }
 
     /**
@@ -37,12 +41,11 @@ public abstract class AbstractRegistrationTree<T> {
      * and modification of the returned node. Note that callers should do so in a finally block.
      */
     protected final void releaseLock() {
-        rwLock.writeLock().unlock();
+        writeLock.unlock();
     }
 
     /**
-     * Find an existing, or allocate a fresh, node for a particular path. Must be called with the
-     * read-write lock held.
+     * Find an existing, or allocate a fresh, node for a particular path. Must be called with the lock held.
      *
      * @param path Path to find a node for
      * @return A registration node for the specified path
@@ -68,20 +71,19 @@ public abstract class AbstractRegistrationTree<T> {
     }
 
     /**
-     * Remove a registration from a particular node. This method must not be called while the read-write lock
-     * is held.
+     * Remove a registration from a particular node. This method must not be called while the lock is held.
      *
      * @param node Tree node
      * @param registration Registration instance
      */
     protected final void removeRegistration(@Nonnull final RegistrationTreeNode<T> node, @Nonnull final T registration) {
         // Take the write lock
-        rwLock.writeLock().lock();
+        writeLock.lock();
         try {
             node.removeRegistration(registration);
         } finally {
             // Always release the lock
-            rwLock.writeLock().unlock();
+            writeLock.unlock();
         }
     }
 
@@ -93,8 +95,7 @@ public abstract class AbstractRegistrationTree<T> {
      * @return A snapshot instance.
      */
     @Nonnull public final RegistrationTreeSnapshot<T> takeSnapshot() {
-        final RegistrationTreeSnapshot<T> ret = new RegistrationTreeSnapshot<>(rwLock.readLock(), rootNode);
-        rwLock.readLock().lock();
-        return ret;
+        readLock.lock();
+        return new RegistrationTreeSnapshot<>(readLock, rootNode);
     }
 }
index 530359f7c244a2c386d4e6a02905acfd62da3c0b..bd895dcaee40741c55b503f46a1a0f909528333e 100644 (file)
@@ -29,6 +29,7 @@ public class AbstractRegistrationTreeTest extends AbstractRegistrationTree<Objec
         this.takeLock();
         this.addRegistration(registrationTreeNode, registration);
         assertTrue(registrationTreeNode.getRegistrations().contains(registration));
+        this.releaseLock();
 
         this.removeRegistration(registrationTreeNode, registration);
         assertFalse(registrationTreeNode.getRegistrations().contains(registration));
@@ -41,4 +42,4 @@ public class AbstractRegistrationTreeTest extends AbstractRegistrationTree<Objec
     public void unlockTest() throws Exception {
         this.releaseLock();
     }
-}
\ No newline at end of file
+}