jaroslav@1890: /* jaroslav@1890: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1890: * jaroslav@1890: * This code is free software; you can redistribute it and/or modify it jaroslav@1890: * under the terms of the GNU General Public License version 2 only, as jaroslav@1890: * published by the Free Software Foundation. Oracle designates this jaroslav@1890: * particular file as subject to the "Classpath" exception as provided jaroslav@1890: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1890: * jaroslav@1890: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1890: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1890: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1890: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1890: * accompanied this code). jaroslav@1890: * jaroslav@1890: * You should have received a copy of the GNU General Public License version jaroslav@1890: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1890: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1890: * jaroslav@1890: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1890: * or visit www.oracle.com if you need additional information or have any jaroslav@1890: * questions. jaroslav@1890: */ jaroslav@1890: jaroslav@1890: /* jaroslav@1890: * This file is available under and governed by the GNU General Public jaroslav@1890: * License version 2 only, as published by the Free Software Foundation. jaroslav@1890: * However, the following notice accompanied the original version of this jaroslav@1890: * file: jaroslav@1890: * jaroslav@1890: * Written by Doug Lea with assistance from members of JCP JSR-166 jaroslav@1890: * Expert Group and released to the public domain, as explained at jaroslav@1890: * http://creativecommons.org/publicdomain/zero/1.0/ jaroslav@1890: */ jaroslav@1890: jaroslav@1890: package java.util.concurrent; jaroslav@1890: import java.util.concurrent.locks.*; jaroslav@1890: import java.util.concurrent.atomic.*; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A synchronization aid that allows one or more threads to wait until jaroslav@1890: * a set of operations being performed in other threads completes. jaroslav@1890: * jaroslav@1890: *

A {@code CountDownLatch} is initialized with a given count. jaroslav@1890: * The {@link #await await} methods block until the current count reaches jaroslav@1890: * zero due to invocations of the {@link #countDown} method, after which jaroslav@1890: * all waiting threads are released and any subsequent invocations of jaroslav@1890: * {@link #await await} return immediately. This is a one-shot phenomenon jaroslav@1890: * -- the count cannot be reset. If you need a version that resets the jaroslav@1890: * count, consider using a {@link CyclicBarrier}. jaroslav@1890: * jaroslav@1890: *

A {@code CountDownLatch} is a versatile synchronization tool jaroslav@1890: * and can be used for a number of purposes. A jaroslav@1890: * {@code CountDownLatch} initialized with a count of one serves as a jaroslav@1890: * simple on/off latch, or gate: all threads invoking {@link #await await} jaroslav@1890: * wait at the gate until it is opened by a thread invoking {@link jaroslav@1890: * #countDown}. A {@code CountDownLatch} initialized to N jaroslav@1890: * can be used to make one thread wait until N threads have jaroslav@1890: * completed some action, or some action has been completed N times. jaroslav@1890: * jaroslav@1890: *

A useful property of a {@code CountDownLatch} is that it jaroslav@1890: * doesn't require that threads calling {@code countDown} wait for jaroslav@1890: * the count to reach zero before proceeding, it simply prevents any jaroslav@1890: * thread from proceeding past an {@link #await await} until all jaroslav@1890: * threads could pass. jaroslav@1890: * jaroslav@1890: *

Sample usage: Here is a pair of classes in which a group jaroslav@1890: * of worker threads use two countdown latches: jaroslav@1890: *

jaroslav@1890: * jaroslav@1890: *
jaroslav@1890:  * class Driver { // ...
jaroslav@1890:  *   void main() throws InterruptedException {
jaroslav@1890:  *     CountDownLatch startSignal = new CountDownLatch(1);
jaroslav@1890:  *     CountDownLatch doneSignal = new CountDownLatch(N);
jaroslav@1890:  *
jaroslav@1890:  *     for (int i = 0; i < N; ++i) // create and start threads
jaroslav@1890:  *       new Thread(new Worker(startSignal, doneSignal)).start();
jaroslav@1890:  *
jaroslav@1890:  *     doSomethingElse();            // don't let run yet
jaroslav@1890:  *     startSignal.countDown();      // let all threads proceed
jaroslav@1890:  *     doSomethingElse();
jaroslav@1890:  *     doneSignal.await();           // wait for all to finish
jaroslav@1890:  *   }
jaroslav@1890:  * }
jaroslav@1890:  *
jaroslav@1890:  * class Worker implements Runnable {
jaroslav@1890:  *   private final CountDownLatch startSignal;
jaroslav@1890:  *   private final CountDownLatch doneSignal;
jaroslav@1890:  *   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
jaroslav@1890:  *      this.startSignal = startSignal;
jaroslav@1890:  *      this.doneSignal = doneSignal;
jaroslav@1890:  *   }
jaroslav@1890:  *   public void run() {
jaroslav@1890:  *      try {
jaroslav@1890:  *        startSignal.await();
jaroslav@1890:  *        doWork();
jaroslav@1890:  *        doneSignal.countDown();
jaroslav@1890:  *      } catch (InterruptedException ex) {} // return;
jaroslav@1890:  *   }
jaroslav@1890:  *
jaroslav@1890:  *   void doWork() { ... }
jaroslav@1890:  * }
jaroslav@1890:  *
jaroslav@1890:  * 
jaroslav@1890: * jaroslav@1890: *

Another typical usage would be to divide a problem into N parts, jaroslav@1890: * describe each part with a Runnable that executes that portion and jaroslav@1890: * counts down on the latch, and queue all the Runnables to an jaroslav@1890: * Executor. When all sub-parts are complete, the coordinating thread jaroslav@1890: * will be able to pass through await. (When threads must repeatedly jaroslav@1890: * count down in this way, instead use a {@link CyclicBarrier}.) jaroslav@1890: * jaroslav@1890: *

jaroslav@1890:  * class Driver2 { // ...
jaroslav@1890:  *   void main() throws InterruptedException {
jaroslav@1890:  *     CountDownLatch doneSignal = new CountDownLatch(N);
jaroslav@1890:  *     Executor e = ...
jaroslav@1890:  *
jaroslav@1890:  *     for (int i = 0; i < N; ++i) // create and start threads
jaroslav@1890:  *       e.execute(new WorkerRunnable(doneSignal, i));
jaroslav@1890:  *
jaroslav@1890:  *     doneSignal.await();           // wait for all to finish
jaroslav@1890:  *   }
jaroslav@1890:  * }
jaroslav@1890:  *
jaroslav@1890:  * class WorkerRunnable implements Runnable {
jaroslav@1890:  *   private final CountDownLatch doneSignal;
jaroslav@1890:  *   private final int i;
jaroslav@1890:  *   WorkerRunnable(CountDownLatch doneSignal, int i) {
jaroslav@1890:  *      this.doneSignal = doneSignal;
jaroslav@1890:  *      this.i = i;
jaroslav@1890:  *   }
jaroslav@1890:  *   public void run() {
jaroslav@1890:  *      try {
jaroslav@1890:  *        doWork(i);
jaroslav@1890:  *        doneSignal.countDown();
jaroslav@1890:  *      } catch (InterruptedException ex) {} // return;
jaroslav@1890:  *   }
jaroslav@1890:  *
jaroslav@1890:  *   void doWork() { ... }
jaroslav@1890:  * }
jaroslav@1890:  *
jaroslav@1890:  * 
jaroslav@1890: * jaroslav@1890: *

Memory consistency effects: Until the count reaches jaroslav@1890: * zero, actions in a thread prior to calling jaroslav@1890: * {@code countDown()} jaroslav@1890: * happen-before jaroslav@1890: * actions following a successful return from a corresponding jaroslav@1890: * {@code await()} in another thread. jaroslav@1890: * jaroslav@1890: * @since 1.5 jaroslav@1890: * @author Doug Lea jaroslav@1890: */ jaroslav@1890: public class CountDownLatch { jaroslav@1890: /** jaroslav@1890: * Synchronization control For CountDownLatch. jaroslav@1890: * Uses AQS state to represent count. jaroslav@1890: */ jaroslav@1890: private static final class Sync extends AbstractQueuedSynchronizer { jaroslav@1890: private static final long serialVersionUID = 4982264981922014374L; jaroslav@1890: jaroslav@1890: Sync(int count) { jaroslav@1890: setState(count); jaroslav@1890: } jaroslav@1890: jaroslav@1890: int getCount() { jaroslav@1890: return getState(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: protected int tryAcquireShared(int acquires) { jaroslav@1890: return (getState() == 0) ? 1 : -1; jaroslav@1890: } jaroslav@1890: jaroslav@1890: protected boolean tryReleaseShared(int releases) { jaroslav@1890: // Decrement count; signal when transition to zero jaroslav@1890: for (;;) { jaroslav@1890: int c = getState(); jaroslav@1890: if (c == 0) jaroslav@1890: return false; jaroslav@1890: int nextc = c-1; jaroslav@1890: if (compareAndSetState(c, nextc)) jaroslav@1890: return nextc == 0; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: private final Sync sync; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Constructs a {@code CountDownLatch} initialized with the given count. jaroslav@1890: * jaroslav@1890: * @param count the number of times {@link #countDown} must be invoked jaroslav@1890: * before threads can pass through {@link #await} jaroslav@1890: * @throws IllegalArgumentException if {@code count} is negative jaroslav@1890: */ jaroslav@1890: public CountDownLatch(int count) { jaroslav@1890: if (count < 0) throw new IllegalArgumentException("count < 0"); jaroslav@1890: this.sync = new Sync(count); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Causes the current thread to wait until the latch has counted down to jaroslav@1890: * zero, unless the thread is {@linkplain Thread#interrupt interrupted}. jaroslav@1890: * jaroslav@1890: *

If the current count is zero then this method returns immediately. jaroslav@1890: * jaroslav@1890: *

If the current count is greater than zero then the current jaroslav@1890: * thread becomes disabled for thread scheduling purposes and lies jaroslav@1890: * dormant until one of two things happen: jaroslav@1890: *

jaroslav@1890: * jaroslav@1890: *

If the current thread: jaroslav@1890: *

jaroslav@1890: * then {@link InterruptedException} is thrown and the current thread's jaroslav@1890: * interrupted status is cleared. jaroslav@1890: * jaroslav@1890: * @throws InterruptedException if the current thread is interrupted jaroslav@1890: * while waiting jaroslav@1890: */ jaroslav@1890: public void await() throws InterruptedException { jaroslav@1890: sync.acquireSharedInterruptibly(1); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Causes the current thread to wait until the latch has counted down to jaroslav@1890: * zero, unless the thread is {@linkplain Thread#interrupt interrupted}, jaroslav@1890: * or the specified waiting time elapses. jaroslav@1890: * jaroslav@1890: *

If the current count is zero then this method returns immediately jaroslav@1890: * with the value {@code true}. jaroslav@1890: * jaroslav@1890: *

If the current count is greater than zero then the current jaroslav@1890: * thread becomes disabled for thread scheduling purposes and lies jaroslav@1890: * dormant until one of three things happen: jaroslav@1890: *

jaroslav@1890: * jaroslav@1890: *

If the count reaches zero then the method returns with the jaroslav@1890: * value {@code true}. jaroslav@1890: * jaroslav@1890: *

If the current thread: jaroslav@1890: *

jaroslav@1890: * then {@link InterruptedException} is thrown and the current thread's jaroslav@1890: * interrupted status is cleared. jaroslav@1890: * jaroslav@1890: *

If the specified waiting time elapses then the value {@code false} jaroslav@1890: * is returned. If the time is less than or equal to zero, the method jaroslav@1890: * will not wait at all. jaroslav@1890: * jaroslav@1890: * @param timeout the maximum time to wait jaroslav@1890: * @param unit the time unit of the {@code timeout} argument jaroslav@1890: * @return {@code true} if the count reached zero and {@code false} jaroslav@1890: * if the waiting time elapsed before the count reached zero jaroslav@1890: * @throws InterruptedException if the current thread is interrupted jaroslav@1890: * while waiting jaroslav@1890: */ jaroslav@1890: public boolean await(long timeout, TimeUnit unit) jaroslav@1890: throws InterruptedException { jaroslav@1890: return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Decrements the count of the latch, releasing all waiting threads if jaroslav@1890: * the count reaches zero. jaroslav@1890: * jaroslav@1890: *

If the current count is greater than zero then it is decremented. jaroslav@1890: * If the new count is zero then all waiting threads are re-enabled for jaroslav@1890: * thread scheduling purposes. jaroslav@1890: * jaroslav@1890: *

If the current count equals zero then nothing happens. jaroslav@1890: */ jaroslav@1890: public void countDown() { jaroslav@1890: sync.releaseShared(1); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns the current count. jaroslav@1890: * jaroslav@1890: *

This method is typically used for debugging and testing purposes. jaroslav@1890: * jaroslav@1890: * @return the current count jaroslav@1890: */ jaroslav@1890: public long getCount() { jaroslav@1890: return sync.getCount(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a string identifying this latch, as well as its state. jaroslav@1890: * The state, in brackets, includes the String {@code "Count ="} jaroslav@1890: * followed by the current count. jaroslav@1890: * jaroslav@1890: * @return a string identifying this latch, as well as its state jaroslav@1890: */ jaroslav@1890: public String toString() { jaroslav@1890: return super.toString() + "[Count = " + sync.getCount() + "]"; jaroslav@1890: } jaroslav@1890: }