All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mrstampy.kitchensync.util.ResettingLatch Maven / Gradle / Ivy

The newest version!
/*
 * KitchenSync-core Java Library Copyright (C) 2014 Burton Alexander
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * 
 */
package com.github.mrstampy.kitchensync.util;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class encapsulates an {@link AtomicReference} to a
 * {@link CountDownLatch} which is replaced when an await returns. It acts as a
 * gate awaiting a the {@link #getCount()} number of {@link #countDown()}s for
 * cyclic operations. It is designed to be used with a single awaiter ie. a
 * thread which awaits for data to be available from a buffer in a recursive
 * action, awaiting the thread which sets the data to check for conditions and
 * if right trigger a {@link #countDown()}.
 */
public class ResettingLatch {
	private static final Logger log = LoggerFactory.getLogger(ResettingLatch.class);

	private final AtomicReference latch;

	private int count;

	/**
	 * The Constructor.
	 */
	public ResettingLatch() {
		this(1);
	}

	/**
	 * The Constructor.
	 *
	 * @param count
	 *          the count
	 */
	public ResettingLatch(int count) {
		if (count < 1) throw new IllegalArgumentException("Count must be > 0: " + count);

		this.count = count;
		this.latch = new AtomicReference(new CountDownLatch(count));

		log.debug("Initialized ResettableLatch for {} count{}", count, (count > 1) ? "s" : "");
	}

	/**
	 * Returns the outstanding number of {@link #countDown()}s.
	 *
	 * @return the long
	 */
	public long remaining() {
		return latch.get().getCount();
	}

	/**
	 * Await.
	 */
	public void await() {
		try {
			latch.get().await();
		} catch (InterruptedException e) {
			log.error("Unexpected exception", e);
		} finally {
			reset();
		}
	}

	/**
	 * Await.
	 *
	 * @param timeout
	 *          the timeout
	 * @param unit
	 *          the unit
	 * @return true, if await
	 */
	public boolean await(int timeout, TimeUnit unit) {
		try {
			return KiSyUtils.await(latch.get(), timeout, unit);
		} finally {
			reset();
		}
	}

	/**
	 * Count down.
	 */
	public void countDown() {
		latch.get().countDown();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return latch.get().toString();
	}

	private void reset() {
		latch.set(new CountDownLatch(getCount()));
	}

	/**
	 * Gets the count.
	 *
	 * @return the count
	 */
	public int getCount() {
		return count;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy