Clover Coverage Report - Backport Util Concurrent v3.0
Coverage timestamp: Fri May 9 2008 11:05:23 EST
../../../../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
62   439   28   5.64
26   117   0.45   5.5
11     2.55  
2    
 
  CyclicBarrier       Line # 104 62 28 97% 0.969697
  CyclicBarrier.Generation       Line # 116 0 0 - -1.0
 
  (18)
 
1    /*
2    * Written by Doug Lea with assistance from members of JCP JSR-166
3    * Expert Group and released to the public domain, as explained at
4    * http://creativecommons.org/licenses/publicdomain
5    */
6   
7    package edu.emory.mathcs.backport.java.util.concurrent;
8    import edu.emory.mathcs.backport.java.util.concurrent.locks.*;
9    import edu.emory.mathcs.backport.java.util.concurrent.helpers.*;
10   
11    /**
12    * A synchronization aid that allows a set of threads to all wait for
13    * each other to reach a common barrier point. CyclicBarriers are
14    * useful in programs involving a fixed sized party of threads that
15    * must occasionally wait for each other. The barrier is called
16    * <em>cyclic</em> because it can be re-used after the waiting threads
17    * are released.
18    *
19    * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
20    * that is run once per barrier point, after the last thread in the party
21    * arrives, but before any threads are released.
22    * This <em>barrier action</em> is useful
23    * for updating shared-state before any of the parties continue.
24    *
25    * <p><b>Sample usage:</b> Here is an example of
26    * using a barrier in a parallel decomposition design:
27    * <pre>
28    * class Solver {
29    * final int N;
30    * final float[][] data;
31    * final CyclicBarrier barrier;
32    *
33    * class Worker implements Runnable {
34    * int myRow;
35    * Worker(int row) { myRow = row; }
36    * public void run() {
37    * while (!done()) {
38    * processRow(myRow);
39    *
40    * try {
41    * barrier.await();
42    * } catch (InterruptedException ex) {
43    * return;
44    * } catch (BrokenBarrierException ex) {
45    * return;
46    * }
47    * }
48    * }
49    * }
50    *
51    * public Solver(float[][] matrix) {
52    * data = matrix;
53    * N = matrix.length;
54    * barrier = new CyclicBarrier(N,
55    * new Runnable() {
56    * public void run() {
57    * mergeRows(...);
58    * }
59    * });
60    * for (int i = 0; i < N; ++i)
61    * new Thread(new Worker(i)).start();
62    *
63    * waitUntilDone();
64    * }
65    * }
66    * </pre>
67    * Here, each worker thread processes a row of the matrix then waits at the
68    * barrier until all rows have been processed. When all rows are processed
69    * the supplied {@link Runnable} barrier action is executed and merges the
70    * rows. If the merger
71    * determines that a solution has been found then <tt>done()</tt> will return
72    * <tt>true</tt> and each worker will terminate.
73    *
74    * <p>If the barrier action does not rely on the parties being suspended when
75    * it is executed, then any of the threads in the party could execute that
76    * action when it is released. To facilitate this, each invocation of
77    * {@link #await} returns the arrival index of that thread at the barrier.
78    * You can then choose which thread should execute the barrier action, for
79    * example:
80    * <pre> if (barrier.await() == 0) {
81    * // log the completion of this iteration
82    * }</pre>
83    *
84    * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
85    * for failed synchronization attempts: If a thread leaves a barrier
86    * point prematurely because of interruption, failure, or timeout, all
87    * other threads waiting at that barrier point will also leave
88    * abnormally via {@link BrokenBarrierException} (or
89    * {@link InterruptedException} if they too were interrupted at about
90    * the same time).
91    *
92    * <p>Memory consistency effects: Actions in a thread prior to calling
93    * {@code await()}
94    * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
95    * actions that are part of the barrier action, which in turn
96    * <i>happen-before</i> actions following a successful return from the
97    * corresponding {@code await()} in other threads.
98    *
99    * @since 1.5
100    * @see CountDownLatch
101    *
102    * @author Doug Lea
103    */
 
104    public class CyclicBarrier {
105    /**
106    * Each use of the barrier is represented as a generation instance.
107    * The generation changes whenever the barrier is tripped, or
108    * is reset. There can be many generations associated with threads
109    * using the barrier - due to the non-deterministic way the lock
110    * may be allocated to waiting threads - but only one of these
111    * can be active at a time (the one to which <tt>count</tt> applies)
112    * and all the rest are either broken or tripped.
113    * There need not be an active generation if there has been a break
114    * but no subsequent reset.
115    */
 
116    private static class Generation {
117    boolean broken = false;
118    }
119   
120    /** The lock for guarding barrier entry */
121    private final Object lock = new Object();
122    /** The number of parties */
123    private final int parties;
124    /* The command to run when tripped */
125    private final Runnable barrierCommand;
126    /** The current generation */
127    private Generation generation = new Generation();
128   
129    /**
130    * Number of parties still waiting. Counts down from parties to 0
131    * on each generation. It is reset to parties on each new
132    * generation or when broken.
133    */
134    private int count;
135   
136    /**
137    * Updates state on barrier trip and wakes up everyone.
138    * Called only while holding lock.
139    */
 
140  33 toggle private void nextGeneration() {
141    // signal completion of last generation
142  33 lock.notifyAll();
143    // set up next generation
144  33 count = parties;
145  33 generation = new Generation();
146    }
147   
148    /**
149    * Sets current barrier generation as broken and wakes up everyone.
150    * Called only while holding lock.
151    */
 
152  27 toggle private void breakBarrier() {
153  27 generation.broken = true;
154  27 count = parties;
155  27 lock.notifyAll();
156    }
157