Switch to using StampedLock
[mdsal.git] / dom / mdsal-dom-spi / src / main / java / org / opendaylight / mdsal / dom / spi / AbstractRegistrationTree.java
index c51a82405b408e0e3ea3c2f7e27fd48721633f04..6e9c3e4ff7b83acdb5cd88b2b4b1c711bc258ed0 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,8 +71,7 @@ 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
@@ -77,12 +79,12 @@ public abstract class AbstractRegistrationTree<T> {
     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();
         }
     }
 
@@ -94,8 +96,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);
     }
 }