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.yangtools.yang.data.tree.impl;
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import java.lang.invoke.MethodHandles;
12 import java.lang.invoke.VarHandle;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
16 abstract class AbstractCursorAware {
17 private static final Logger LOG = LoggerFactory.getLogger(AbstractCursorAware.class);
18 private static final VarHandle CURSOR;
22 CURSOR = MethodHandles.lookup().findVarHandle(AbstractCursorAware.class, "cursor", AbstractCursor.class);
23 } catch (NoSuchFieldException | IllegalAccessException e) {
24 throw new ExceptionInInitializerError(e);
28 @SuppressWarnings("unused")
29 @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
30 private volatile AbstractCursor<?> cursor;
32 protected <T extends AbstractCursor<?>> T openCursor(final T cursorToOpen) {
33 final var witness = (AbstractCursor<?>) CURSOR.compareAndExchange(this, null, cursorToOpen);
34 if (witness != null) {
35 throw new IllegalStateException(
36 "Modification " + this + " has cursor attached at path " + witness.getRootPath());
41 final void closeCursor(final AbstractCursor<?> cursorToClose) {
42 final var witness = (AbstractCursor<?>) CURSOR.compareAndExchange(this, cursorToClose, null);
43 if (witness != cursorToClose) {
44 LOG.warn("Attempted to close cursor {} while {} is open", cursorToClose, witness);