2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.dom.spi;
10 import java.util.concurrent.locks.Lock;
11 import java.util.concurrent.locks.StampedLock;
12 import javax.annotation.Nonnull;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
16 * An abstract tree of registrations. Allows a read-only snapshot to be taken.
18 * @param <T> Type of registered object
20 public abstract class AbstractRegistrationTree<T> {
21 private final RegistrationTreeNode<T> rootNode = new RegistrationTreeNode<>(null, null);
22 private final Lock writeLock;
23 private final Lock readLock;
25 protected AbstractRegistrationTree() {
26 final StampedLock lock = new StampedLock();
27 readLock = lock.asReadLock();
28 writeLock = lock.asWriteLock();
32 * Acquire the read-write lock. This should be done before invoking {@link #findNodeFor(Iterable)}. This method
33 * must not be called when the lock is already held by this thread.
35 protected final void takeLock() {
40 * Release the read-write lock. This should be done after invocation of {@link #findNodeFor(Iterable)}
41 * and modification of the returned node. Note that callers should do so in a finally block.
43 protected final void releaseLock() {
48 * Find an existing, or allocate a fresh, node for a particular path. Must be called with the lock held.
50 * @param path Path to find a node for
51 * @return A registration node for the specified path
53 @Nonnull protected final RegistrationTreeNode<T> findNodeFor(@Nonnull final Iterable<PathArgument> path) {
54 RegistrationTreeNode<T> walkNode = rootNode;
55 for (final PathArgument arg : path) {
56 walkNode = walkNode.ensureChild(arg);
63 * Add a registration to a particular node. The node must have been returned via {@link #findNodeFor(Iterable)}
64 * and the lock must still be held.
66 * @param node Tree node
67 * @param registration Registration instance
69 protected final void addRegistration(@Nonnull final RegistrationTreeNode<T> node, @Nonnull final T registration) {
70 node.addRegistration(registration);
74 * Remove a registration from a particular node. This method must not be called while the lock is held.
76 * @param node Tree node
77 * @param registration Registration instance
79 protected final void removeRegistration(@Nonnull final RegistrationTreeNode<T> node,
80 @Nonnull final T registration) {
81 // Take the write lock
84 node.removeRegistration(registration);
86 // Always release the lock
92 * Obtain a tree snapshot. This snapshot ensures a consistent view of
93 * registrations. The snapshot should be closed as soon as it is not required,
94 * because each unclosed instance blocks modification of this tree.
96 * @return A snapshot instance.
98 @Nonnull public final RegistrationTreeSnapshot<T> takeSnapshot() {
100 return new RegistrationTreeSnapshot<>(readLock, rootNode);