001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.concurrent;
019
020import javax.annotation.concurrent.ThreadSafe;
021import java.util.concurrent.CountDownLatch;
022
023/**
024 * A one-time latch that holds a value
025 *
026 * @author The TridentSDK Team
027 * @since 0.3-alpha-DP
028 * @param <V> the value type of the latch
029 */
030@ThreadSafe
031public class HeldValueLatch<V> {
032    private final CountDownLatch latch = new CountDownLatch(1);
033    private volatile V value;
034
035    private HeldValueLatch() {
036    }
037
038    /**
039     * Creates a new latch that can hold a value
040     *
041     * @param <V> the type of the value
042     * @return a new value latch
043     */
044    public static <V> HeldValueLatch<V> create() {
045        return new HeldValueLatch<>();
046    }
047
048    /**
049     * Sets the value in the latch
050     *
051     * <p>The effects of setting this only once is unspecified</p>
052     *
053     * <p>This is unsynchronized because all actions prior to counting down <em>happens-before</em> another thread
054     * awaits the value</p>
055     *
056     * @param value the value to set to the latch
057     * @return the value passed in
058     */
059    public V countDown(V value) {
060        this.value = value;
061        latch.countDown();
062        return value;
063    }
064
065    /**
066     * Inspects the latch to find of the object has been counted down
067     *
068     * @return {@code true} if the value has been set
069     */
070    public boolean hasValue() {
071        return this.latch.getCount() == 0;
072    }
073
074    /**
075     * Acquires the value held be the latch, or blocks to wait for the value to become available
076     *
077     * @return the value held by the latch
078     * @throws InterruptedException if the operation was interrupted while blocked
079     */
080    public V await() throws InterruptedException {
081        latch.await();
082        return value;
083    }
084
085    /**
086     * Acquires the value without waiting for the latch to be counted down
087     *
088     * <p>This is still thread-safe, as the internal state is {@code volatile}</p>
089     *
090     * @return the value held by this latch
091     */
092    public V get() {
093        return value;
094    }
095}