| /* |
| * Copyright 2015-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onlab.util; |
| |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.locks.AbstractQueuedSynchronizer; |
| |
| /** |
| * Mutable boolean that allows threads to wait for a specified value. |
| */ |
| public class BlockingBoolean extends AbstractQueuedSynchronizer { |
| |
| private static final int TRUE = 1; |
| private static final int FALSE = 0; |
| |
| /** |
| * Creates a new blocking boolean with the specified value. |
| * |
| * @param value the starting value |
| */ |
| public BlockingBoolean(boolean value) { |
| setState(value ? TRUE : FALSE); |
| } |
| |
| /** |
| * Causes the current thread to wait until the boolean equals the specified |
| * value unless the thread is {@linkplain Thread#interrupt interrupted}. |
| * |
| * @param value specified value |
| * @throws InterruptedException if interrupted while waiting |
| */ |
| public void await(boolean value) throws InterruptedException { |
| acquireSharedInterruptibly(value ? TRUE : FALSE); |
| } |
| |
| /** |
| * Causes the current thread to wait until the boolean equals the specified |
| * value unless the thread is {@linkplain Thread#interrupt interrupted}, |
| * or the specified waiting time elapses. |
| * |
| * @param value specified value |
| * @param timeout the maximum time to wait |
| * @param unit the time unit of the {@code timeout} argument |
| * @return {@code true} if the count reached zero and {@code false} |
| * if the waiting time elapsed before the count reached zero |
| * @throws InterruptedException if interrupted while waiting |
| */ |
| public boolean await(boolean value, long timeout, TimeUnit unit) |
| throws InterruptedException { |
| return tryAcquireSharedNanos(value ? TRUE : FALSE, unit.toNanos(timeout)); |
| } |
| |
| protected int tryAcquireShared(int acquires) { |
| return (getState() == acquires) ? 1 : -1; |
| } |
| |
| /** |
| * Sets the value of the blocking boolean. |
| * |
| * @param value new value |
| */ |
| public void set(boolean value) { |
| releaseShared(value ? TRUE : FALSE); |
| } |
| |
| /** |
| * Gets the value of the blocking boolean. |
| * |
| * @return current value |
| */ |
| public boolean get() { |
| return getState() == TRUE; |
| } |
| |
| protected boolean tryReleaseShared(int releases) { |
| // Signal on state change only |
| int state = getState(); |
| if (state == releases) { |
| return false; |
| } |
| return compareAndSetState(state, releases); |
| } |
| |
| } |