1 7 8 package java.util.concurrent; 9 import java.util.concurrent.locks.*; 10 11 97 public class CyclicBarrier { 98 109 private static class Generation { 110 boolean broken = false; 111 } 112 113 114 private final ReentrantLock lock = new ReentrantLock(); 115 116 private final Condition trip = lock.newCondition(); 117 118 private final int parties; 119 120 private final Runnable barrierCommand; 121 122 private Generation generation = new Generation(); 123 124 129 private int count; 130 131 135 private void nextGeneration() { 136 trip.signalAll(); 138 count = parties; 140 generation = new Generation(); 141 } 142 143 147 private void breakBarrier() { 148 generation.broken = true; 149 count = parties; 150 trip.signalAll(); 151 } 152 153 156 private int dowait(boolean timed, long nanos) 157 throws InterruptedException , BrokenBarrierException , 158 TimeoutException { 159 final ReentrantLock lock = this.lock; 160 lock.lock(); 161 try { 162 final Generation g = generation; 163 164 if (g.broken) 165 throw new BrokenBarrierException (); 166 167 if (Thread.interrupted()) { 168 breakBarrier(); 169 throw new InterruptedException (); 170 } 171 172 int index = --count; 173 if (index == 0) { boolean ranAction = false; 175 try { 176 final Runnable command = barrierCommand; 177 if (command != null) 178 command.run(); 179 ranAction = true; 180 nextGeneration(); 181 return 0; 182 } finally { 183 if (!ranAction) 184 breakBarrier(); 185 } 186 } 187 188 for (;;) { 190 try { 191 if (!timed) 192 trip.await(); 193 else if (nanos > 0L) 194 nanos = trip.awaitNanos(nanos); 195 } catch (InterruptedException ie) { 196 if (g == generation && ! g.broken) { 197 breakBarrier(); 198 throw ie; 199 } else { 200 Thread.currentThread().interrupt(); 204 } 205 } 206 207 if (g.broken) 208 throw new BrokenBarrierException (); 209 210 if (g != generation) 211 return index; 212 213 if (timed && nanos <= 0L) { 214 breakBarrier(); 215 throw new TimeoutException (); 216 } 217 } 218 } finally { 219 lock.unlock(); 220 } 221 } 222 223 236 public CyclicBarrier(int parties, Runnable barrierAction) { 237 if (parties <= 0) throw new IllegalArgumentException (); 238 this.parties = parties; 239 this.count = parties; 240 this.barrierCommand = barrierAction; 241 } 242 243 253 public CyclicBarrier(int parties) { 254 this(parties, null); 255 } 256 257 261 public int getParties() { 262 return parties; 263 } 264 265 319 public int await() throws InterruptedException , BrokenBarrierException { 320 try { 321 return dowait(false, 0L); 322 } catch (TimeoutException toe) { 323 throw new Error (toe); } 325 } 326 327 389 public int await(long timeout, TimeUnit unit) 390 throws InterruptedException , 391 BrokenBarrierException , 392 TimeoutException { 393 return dowait(true, unit.toNanos(timeout)); 394 } 395 396 403 public boolean isBroken() { 404 final ReentrantLock lock = this.lock; 405 lock.lock(); 406 try { 407 return generation.broken; 408 } finally { 409 lock.unlock(); 410 } 411 } 412 413 422 public void reset() { 423 final ReentrantLock lock = this.lock; 424 lock.lock(); 425 try { 426 breakBarrier(); nextGeneration(); } finally { 429 lock.unlock(); 430 } 431 } 432 433 439 public int getNumberWaiting() { 440 final ReentrantLock lock = this.lock; 441 lock.lock(); 442 try { 443 return parties - count; 444 } finally { 445 lock.unlock(); 446 } 447 } 448 } 449
| Popular Tags
|