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.controller.md.sal.dom.spi;
10 import java.util.concurrent.locks.ReadWriteLock;
11 import java.util.concurrent.locks.ReentrantReadWriteLock;
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 ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
22 private final RegistrationTreeNode<T> rootNode = new RegistrationTreeNode<>(null, null);
24 protected AbstractRegistrationTree() {
29 * Acquire the read-write lock. This should be done before invoking {@link #findNodeFor(Iterable)}.
31 protected final void takeLock() {
32 rwLock.writeLock().lock();
36 * Release the read-write lock. This should be done after invocation of {@link #findNodeFor(Iterable)}
37 * and modification of the returned node. Note that callers should do so in a finally block.
39 protected final void releaseLock() {
40 rwLock.writeLock().unlock();
44 * Find an existing, or allocate a fresh, node for a particular path. Must be called with the
45 * read-write lock held.
47 * @param path Path to find a node for
48 * @return A registration node for the specified path
50 @Nonnull protected final RegistrationTreeNode<T> findNodeFor(@Nonnull final Iterable<PathArgument> path) {
51 RegistrationTreeNode<T> walkNode = rootNode;
52 for (final PathArgument arg : path) {
53 walkNode = walkNode.ensureChild(arg);
60 * Add a registration to a particular node. The node must have been returned via {@link #findNodeFor(Iterable)}
61 * and the lock must still be held.
63 * @param node Tree node
64 * @param registration Registration instance
66 protected final void addRegistration(@Nonnull final RegistrationTreeNode<T> node, @Nonnull final T registration) {
67 node.addRegistration(registration);
71 * Remove a registration from a particular node. This method must not be called while the read-write lock
74 * @param node Tree node
75 * @param registration Registration instance
77 protected final void removeRegistration(@Nonnull final RegistrationTreeNode<T> node, @Nonnull final T registration) {
78 // Take the write lock
79 rwLock.writeLock().lock();
81 node.removeRegistration(registration);
83 // Always release the lock
84 rwLock.writeLock().unlock();
89 * Obtain a tree snapshot. This snapshot ensures a consistent view of
90 * registrations. The snapshot should be closed as soon as it is not required,
91 * because each unclosed instance blocks modification of this tree.
93 * @return A snapshot instance.
95 @Nonnull public final RegistrationTreeSnapshot<T> takeSnapshot() {
96 final RegistrationTreeSnapshot<T> ret = new RegistrationTreeSnapshot<>(rwLock.readLock(), rootNode);
97 rwLock.readLock().lock();