aa2d97a99989e2689554c02ab549e62302a55135
[yangtools.git] / common / concepts / src / main / java / org / opendaylight / yangtools / concepts / AbstractRegistration.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.concepts;
9
10 import com.google.common.base.MoreObjects;
11 import com.google.common.base.MoreObjects.ToStringHelper;
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.lang.invoke.MethodHandles;
14 import java.lang.invoke.VarHandle;
15
16 /**
17  * Utility registration handle. It is a convenience for register-style method which can return an AutoCloseable realized
18  * by a subclass of this class. Invoking the close() method triggers unregistration of the state the method installed.
19  */
20 public abstract class AbstractRegistration implements Registration {
21     private static final VarHandle CLOSED;
22
23     // All access needs to go through this handle
24     @SuppressWarnings("unused")
25     @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
26     private volatile byte closed;
27
28     static {
29         try {
30             CLOSED = MethodHandles.lookup().findVarHandle(AbstractRegistration.class, "closed", byte.class);
31         } catch (ReflectiveOperationException e) {
32             throw new ExceptionInInitializerError(e);
33         }
34     }
35
36     /**
37      * Remove the state referenced by this registration. This method is guaranteed to be called at most once.
38      * Referenced state must be retained until this method is invoked.
39      */
40     protected abstract void removeRegistration();
41
42     /**
43      * Query the state of this registration. Returns true if it was closed. Equivalent of {@code !notClosed()}.
44      *
45      * @return true if the registration was closed, false otherwise.
46      */
47     public final boolean isClosed() {
48         return (byte) CLOSED.getAcquire(this) != 0;
49     }
50
51     /**
52      * Query the state of this registration. Returns false if it was closed. Equivalent of {@code !isClosed()}.
53      *
54      * @return false if the registration was closed, true otherwise.
55      */
56     public final boolean notClosed() {
57         return (byte) CLOSED.getAcquire(this) == 0;
58     }
59
60     @Override
61     public final void close() {
62         // We want full setVolatile() memory semantics here, as all state before calling this method
63         // needs to be visible
64         if (CLOSED.compareAndSet(this, (byte) 0, (byte) 1)) {
65             removeRegistration();
66         }
67     }
68
69     @Override
70     public final String toString() {
71         return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString();
72     }
73
74     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
75         return toStringHelper.add("closed", isClosed());
76     }
77 }