00001
00013 module mango.locks.Countdown;
00014
00015 private {
00016 import std.thread;
00017
00018 import mango.sys.Atomic;
00019
00020 import mango.locks.Utils;
00021 import mango.locks.LockImpl;
00022 import mango.locks.TimeUnit;
00023 import mango.locks.Exceptions;
00024 }
00025
00099 class CountDownLatch {
00100
00101
00102
00103
00104
00105 private final class Sync : AbstractLock {
00106 this(int count) {
00107 state = count;
00108 }
00109
00110 int getCount() {
00111 return state;
00112 }
00113
00114 int tryAcquireShared(int acquires) {
00115 return state == 0? 1 : -1;
00116 }
00117
00118 bool tryReleaseShared(int releases) {
00119
00120 for (;;) {
00121 int c = state;
00122 if (c == 0)
00123 return false;
00124 int nextc = c-1;
00125 if (Atomic.compareAndSet32(&state_, c, nextc))
00126 return nextc == 0;
00127 }
00128 }
00129 }
00130
00131 private Sync sync;
00132
00140 this(int count) {
00141 if (count < 0)
00142 throw new IllegalArgumentException();
00143 this.sync = new Sync(count);
00144 }
00145
00156 void wait() {
00157 sync.acquireShared(1);
00158 }
00159
00186 bool wait(long timeout, TimeUnit unit) {
00187 return sync.tryAcquireSharedNanos(1, toNanos(timeout,unit));
00188 }
00189
00200 void countDown() {
00201 sync.releaseShared(1);
00202 }
00203
00209 long count() {
00210 return sync.getCount();
00211 }
00212
00219 char[] toString() {
00220 char[16] buf;
00221
00222 return super.toString() ~ "[Count = " ~
00223 itoa(buf, sync.getCount()) ~ "]";
00224 }
00225
00226 unittest {
00227 class Worker {
00228 private final CountDownLatch done;
00229 this(CountDownLatch d) { done = d; }
00230
00231 ThreadReturn run() {
00232 version (LocksVerboseUnittest)
00233 printf("counting down...\n");
00234 for (int k=0;k<10000; k++){}
00235 done.countDown();
00236 return 0;
00237 }
00238 }
00239 int N = 5;
00240 version (LocksVerboseUnittest)
00241 printf("starting locks.countdown unittest\n");
00242 CountDownLatch done = new CountDownLatch(N);
00243 for (int i = 0; i < N; ++i) {
00244 Worker w = new Worker(done);
00245 Thread t = new Thread(&w.run);
00246 t.start();
00247 }
00248 for (int k=0;k<10000; k++){}
00249 done.wait();
00250 version (LocksVerboseUnittest)
00251 printf("finished locks.countdown unittest\n");
00252 }
00253 }