Switch to using StampedLock
[mdsal.git] / dom / mdsal-dom-spi / src / main / java / org / opendaylight / mdsal / dom / spi / AbstractRegistrationTree.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);
     }
 }