Mercurial > hg > blitz_condensed
diff src/EDU/oswego/cs/dl/util/concurrent/CountDown.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/EDU/oswego/cs/dl/util/concurrent/CountDown.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,122 @@ +/* + File: CountDown.java + + Originally written by Doug Lea and released into the public domain. + This may be used for any purposes whatsoever without acknowledgment. + Thanks for the assistance and support of Sun Microsystems Labs, + and everyone contributing, testing, and using this code. + + History: + Date Who What + 11Jun1998 dl Create public version +*/ + +package EDU.oswego.cs.dl.util.concurrent; + +/** + * A CountDown can serve as a simple one-shot barrier. + * A Countdown is initialized + * with a given count value. Each release decrements the count. + * All acquires block until the count reaches zero. Upon reaching + * zero all current acquires are unblocked and all + * subsequent acquires pass without blocking. This is a one-shot + * phenomenon -- the count cannot be reset. + * If you need a version that resets the count, consider + * using a Barrier. + * <p> + * <b>Sample usage.</b> Here are a set of classes in which + * a group of worker threads use a countdown to + * notify a driver when all threads are complete. + * <pre> + * class Worker implements Runnable { + * private final CountDown done; + * Worker(CountDown d) { done = d; } + * public void run() { + * doWork(); + * done.release(); + * } + * } + * + * class Driver { // ... + * void main() { + * CountDown done = new CountDown(N); + * for (int i = 0; i < N; ++i) + * new Thread(new Worker(done)).start(); + * doSomethingElse(); + * done.acquire(); // wait for all to finish + * } + * } + * </pre> + * + * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] + * +**/ + +public class CountDown implements Sync { + protected final int initialCount_; + protected int count_; + + /** Create a new CountDown with given count value **/ + public CountDown(int count) { count_ = initialCount_ = count; } + + + /* + This could use double-check, but doesn't out of concern + for surprising effects on user programs stemming + from lack of memory barriers with lack of synch. + */ + public void acquire() throws InterruptedException { + if (Thread.interrupted()) throw new InterruptedException(); + synchronized(this) { + while (count_ > 0) + wait(); + } + } + + + public boolean attempt(long msecs) throws InterruptedException { + if (Thread.interrupted()) throw new InterruptedException(); + synchronized(this) { + if (count_ <= 0) + return true; + else if (msecs <= 0) + return false; + else { + long waitTime = msecs; + long start = System.currentTimeMillis(); + for (;;) { + wait(waitTime); + if (count_ <= 0) + return true; + else { + waitTime = msecs - (System.currentTimeMillis() - start); + if (waitTime <= 0) + return false; + } + } + } + } + } + + /** + * Decrement the count. + * After the initialCount'th release, all current and future + * acquires will pass + **/ + public synchronized void release() { + if (--count_ == 0) + notifyAll(); + } + + /** Return the initial count value **/ + public int initialCount() { return initialCount_; } + + + /** + * Return the current count value. + * This is just a snapshot value, that may change immediately + * after returning. + **/ + public synchronized int currentCount() { return count_; } +} +