View Javadoc
1   //******************************************************************************
2   //
3   // File:    ParallelRegion.java
4   // Package: edu.rit.pj
5   // Unit:    Class edu.rit.pj.ParallelRegion
6   //
7   // This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.pj;
41  
42  import java.util.Iterator;
43  
44  import edu.rit.util.LongRange;
45  import edu.rit.util.Range;
46  
47  /**
48   * Class ParallelRegion is the abstract base class for a parallel region that is
49   * executed by a {@linkplain ParallelTeam} of threads.
50   * <P>
51   * To execute a parallel region, create a {@linkplain ParallelTeam} object;
52   * create an instance of a concrete subclass of class ParallelRegion; and pass
53   * this instance to the parallel team's <code>execute()</code> method. You can do
54   * all this using an anonymous inner class; for example:
55   * <PRE>
56   *     new ParallelTeam().execute (new ParallelRegion()
57   *         {
58   *         // Shared variable declarations
59   *         . . .
60   *         public void start()
61   *             {
62   *             // Initialization code
63   *             . . .
64   *             }
65   *         public void run()
66   *             {
67   *             // Thread private variable declarations
68   *             // Parallel code
69   *             . . .
70   *             }
71   *         public void finish()
72   *             {
73   *             // Finalization code
74   *             . . .
75   *             }
76   *         });
77   * </PRE>
78   * <P>
79   * The parallel team's <code>execute()</code> method does the following. The
80   * parallel team has a certain number of threads <I>K</I>, where <I>K</I> was
81   * specified when the parallel team was constructed. The main thread is the
82   * thread calling the parallel team's <code>execute()</code> method. The main thread
83   * calls the parallel region's <code>start()</code> method. When the
84   * <code>start()</code> method returns, all the team threads call the parallel
85   * region's <code>run()</code> method concurrently. When all the team threads have
86   * returned from the <code>run()</code> method, the main thread calls the parallel
87   * region's <code>finish()</code> method. When the <code>finish()</code> method returns,
88   * the main thread returns from the parallel team's <code>execute()</code> method.
89   * <P>
90   * Variables to be shared by all threads in the team may be declared as fields
91   * of the ParallelRegion subclass. The <code>start()</code> method is intended for
92   * performing initialization in a single thread before parallel execution
93   * begins. If no such initialization is needed, omit the <code>start()</code>
94   * method. The <code>run()</code> method contains code to be executed in parallel by
95   * all threads in the team. Variables that are private to each thread may be
96   * declared inside the <code>run()</code> method. The <code>finish()</code> method is
97   * intended for performing finalization in a single thread after parallel
98   * execution ends. If no such finalization is needed, omit the <code>finish()</code>
99   * method.
100  * <P>
101  * If the parallel region's <code>start()</code> method throws an exception, the
102  * parallel team's <code>execute()</code> method throws that same exception, and the
103  * <code>run()</code> method is not called.
104  * <P>
105  * If the parallel region's <code>run()</code> method throws an exception in one of
106  * the team threads, the exception's stack trace is printed on the standard
107  * error, the parallel team waits until all the other team threads have returned
108  * from the <code>run()</code> method, then the parallel team's <code>execute()</code>
109  * method throws that same exception, and the parallel region's
110  * <code>finish()</code> method is not called. If the parallel region's
111  * <code>run()</code> method throws an exception in more than one of the team
112  * threads, each exception's stack trace is printed on the standard error, the
113  * parallel team waits until all the other team threads have returned from the
114  * <code>run()</code> method, then the parallel team's <code>execute()</code> method
115  * throws a {@linkplain MultipleParallelException} wrapping all the thrown
116  * exceptions, and the parallel region's <code>finish()</code> method is not called.
117  * <P>
118  * If the parallel region's <code>finish()</code> method throws an exception, the
119  * parallel team's <code>execute()</code> method throws that same exception.
120  *
121  * @author Alan Kaminsky
122  * @version 11-Nov-2007
123  */
124 public abstract class ParallelRegion
125         extends ParallelConstruct {
126 
127 // Hidden data members.
128     // Default lock for critical() and criticalNonexclusive() methods.
129     private Lock myLock = new Lock();
130 
131 // Exported constructors.
132     /**
133      * Construct a new parallel region.
134      */
135     public ParallelRegion() {
136         super();
137     }
138 
139 // Exported operations.
140     /**
141      * Perform initialization actions before parallel execution begins. Only one
142      * thread calls the <code>start()</code> method.
143      * <P>
144      * The <code>start()</code> method may be overridden in a subclass. If not
145      * overridden, the <code>start()</code> method does nothing.
146      *
147      * @exception Exception The <code>start()</code> method may throw any exception.
148      * @throws java.lang.Exception if any.
149      */
150     public void start()
151             throws Exception {
152     }
153 
154     /**
155      * Execute parallel code. All threads of the parallel team call the
156      * <code>run()</code> method concurrently.
157      * <P>
158      * The <code>run()</code> method must be implemented in a subclass.
159      *
160      * @exception Exception The <code>run()</code> method may throw any exception.
161      * @throws java.lang.Exception if any.
162      */
163     public abstract void run()
164             throws Exception;
165 
166     /**
167      * Perform finalization actions after parallel execution ends. Only one
168      * thread calls the <code>finish()</code> method.
169      * <P>
170      * The <code>finish()</code> method may be overridden in a subclass. If not
171      * overridden, the <code>finish()</code> method does nothing.
172      *
173      * @exception Exception The <code>finish()</code> method may throw any
174      * exception.
175      * @throws java.lang.Exception if any.
176      */
177     public void finish()
178             throws Exception {
179     }
180 
181     /**
182      * Execute a parallel for loop within this parallel region. For further
183      * information, see class {@linkplain IntegerForLoop}. The loop index goes
184      * from <code>first</code> (inclusive) to <code>last</code> (inclusive) in steps of
185      * +1. If <code>first</code> is greater than <code>last</code>, then no loop
186      * iterations are performed. At the end of the parallel for loop, the
187      * parallel team threads wait for each other at a barrier.
188      * <P>
189      * <I>Note:</I> Either all threads in the parallel team must call the
190      * <code>execute()</code> method with identical arguments, or none of the
191      * threads must call the <code>execute()</code> method.
192      *
193      * @param first First loop index.
194      * @param last Last loop index.
195      * @param theLoop Parallel for loop.
196      * @exception NullPointerException (unchecked exception) Thrown if
197      * <code>theLoop</code> is null.
198      * @exception IllegalStateException (unchecked exception) Thrown if no
199      * parallel team is executing this parallel region.
200      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
201      * an exception.
202      * @throws java.lang.Exception if any.
203      */
204     public final void execute(int first,
205             int last,
206             IntegerForLoop theLoop)
207             throws Exception {
208         execute(first, last, theLoop, BarrierAction.WAIT);
209     }
210 
211     /**
212      * Execute a parallel for loop within this parallel region. For further
213      * information, see class {@linkplain IntegerForLoop}. The loop index goes
214      * from <code>first</code> (inclusive) to <code>last</code> (inclusive) in steps of
215      * +1. If <code>first</code> is greater than <code>last</code>, then no loop
216      * iterations are performed. At the end of the parallel for loop, the
217      * parallel team threads encounter a barrier, and their behavior depends on
218      * the given {@linkplain BarrierAction}.
219      * <P>
220      * <I>Note:</I> Either all threads in the parallel team must call the
221      * <code>execute()</code> method with identical arguments, or none of the
222      * threads must call the <code>execute()</code> method.
223      *
224      * @param first First loop index.
225      * @param last Last loop index.
226      * @param theLoop Parallel for loop.
227      * @param action Barrier action.
228      * @exception NullPointerException (unchecked exception) Thrown if
229      * <code>theLoop</code> is null. Thrown if
230      * <code>action</code> is null.
231      * @exception IllegalStateException (unchecked exception) Thrown if no
232      * parallel team is executing this parallel region.
233      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
234      * an exception.
235      * @throws java.lang.Exception if any.
236      */
237     public final void execute(int first,
238             int last,
239             IntegerForLoop theLoop,
240             BarrierAction action)
241             throws Exception {
242         // Verify preconditions.
243         if (theLoop == null) {
244             throw new NullPointerException("ParallelRegion.execute(): Parallel for loop is null");
245         }
246         if (action == null) {
247             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
248         }
249         if (myTeam == null) {
250             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
251         }
252 
253         try {
254             // Record parallel team.
255             theLoop.myTeam = this.myTeam;
256 
257             // Get current parallel team thread.
258             ParallelTeamThread currentThread = getCurrentThread();
259             int currentIndex = currentThread.myIndex;
260 
261             // Do top-of-parallel-construct processing.
262             IntegerSchedule schedule = null;
263             if (currentThread.arriveAtParallelConstruct()) {
264                 // First thread to arrive sets up the shared parallel for loop
265                 // schedule object and stores it (or an exception if any) in
266                 // each team thread.
267                 try {
268                     schedule = theLoop.schedule();
269                     schedule.commonStart(myTeam.K, new Range(first, last));
270                     for (ParallelTeamThread thread : myTeam.myThread) {
271                         thread.setIntegerSchedule(schedule);
272                     }
273                 } catch (Throwable exc) {
274                     for (ParallelTeamThread thread : myTeam.myThread) {
275                         thread.setConstructException(exc);
276                     }
277                 }
278             }
279 
280             // Get the shared parallel for loop schedule object.
281             schedule = currentThread.getIntegerSchedule();
282             theLoop.mySchedule = schedule;
283 
284             // Prepare to catch exceptions thrown by the parallel for loop body.
285             Throwable runException = null;
286             try {
287                 // Perform per-thread initialization.
288                 theLoop.start();
289 
290                 // Repeatedly get and process a chunk of loop iterations.
291                 Range chunk;
292                 while ((chunk = schedule.commonNext(currentIndex)) != null) {
293                     theLoop.commonRun(chunk.lb(), chunk.ub());
294                 }
295 
296                 // Perform per-thread finalization.
297                 theLoop.finish();
298             } catch (Throwable exc) {
299                 runException = exc;
300                 schedule.myBreak = true;
301             }
302 
303             // Barrier synchronization.
304             action.doBarrier(currentThread);
305 
306             // Propagate any exception thrown by the run() method.
307             ParallelTeam.rethrow(runException);
308         } finally {
309             // Forget parallel team.
310             theLoop.myTeam = null;
311             theLoop.mySchedule = null;
312         }
313     }
314 
315     /**
316      * Execute a parallel for loop within this parallel region. For further
317      * information, see class {@linkplain IntegerStrideForLoop}. The loop index
318      * goes from <code>first</code> (inclusive) to <code>last</code> (inclusive) in
319      * steps of <code>stride</code>. The stride must be positive. If <code>first</code>
320      * is greater than <code>last</code>, then no loop iterations are performed. At
321      * the end of the parallel for loop, the parallel team threads wait for each
322      * other at a barrier.
323      * <P>
324      * <I>Note:</I> Either all threads in the parallel team must call the
325      * <code>execute()</code> method with identical arguments, or none of the
326      * threads must call the <code>execute()</code> method.
327      *
328      * @param first First loop index.
329      * @param last Last loop index.
330      * @param stride Loop index stride, &gt;= 1.
331      * @param theLoop Parallel for loop.
332      * @exception IllegalArgumentException (unchecked exception) Thrown if
333      * <code>stride</code> &lt; 1.
334      * @exception NullPointerException (unchecked exception) Thrown if
335      * <code>theLoop</code> is null.
336      * @exception IllegalStateException (unchecked exception) Thrown if no
337      * parallel team is executing this parallel region.
338      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
339      * an exception.
340      * @throws java.lang.Exception if any.
341      */
342     public final void execute(int first,
343             int last,
344             int stride,
345             IntegerStrideForLoop theLoop)
346             throws Exception {
347         execute(first, last, stride, theLoop, BarrierAction.WAIT);
348     }
349 
350     /**
351      * Execute a parallel for loop within this parallel region. For further
352      * information, see class {@linkplain IntegerStrideForLoop}. The loop index
353      * goes from <code>first</code> (inclusive) to <code>last</code> (inclusive) in
354      * steps of <code>stride</code>. The stride must be positive. If <code>first</code>
355      * is greater than <code>last</code>, then no loop iterations are performed. At
356      * the end of the parallel for loop, the parallel team threads encounter a
357      * barrier, and their behavior depends on the given {@linkplain
358      * BarrierAction}.
359      * <P>
360      * <I>Note:</I> Either all threads in the parallel team must call the
361      * <code>execute()</code> method with identical arguments, or none of the
362      * threads must call the <code>execute()</code> method.
363      *
364      * @param first First loop index.
365      * @param last Last loop index.
366      * @param stride Loop index stride, &gt;= 1.
367      * @param theLoop Parallel for loop.
368      * @param action Barrier action.
369      * @exception IllegalArgumentException (unchecked exception) Thrown if
370      * <code>stride</code> &lt; 1.
371      * @exception NullPointerException (unchecked exception) Thrown if
372      * <code>theLoop</code> is null. Thrown if
373      * <code>action</code> is null.
374      * @exception IllegalStateException (unchecked exception) Thrown if no
375      * parallel team is executing this parallel region.
376      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
377      * an exception.
378      * @throws java.lang.Exception if any.
379      */
380     public final void execute(int first,
381             int last,
382             int stride,
383             IntegerStrideForLoop theLoop,
384             BarrierAction action)
385             throws Exception {
386         // Verify preconditions.
387         if (stride <= 0) {
388             throw new IllegalArgumentException("ParallelRegion.execute(): Stride = " + stride + " illegal");
389         }
390         if (theLoop == null) {
391             throw new NullPointerException("ParallelRegion.execute(): Parallel for loop is null");
392         }
393         if (action == null) {
394             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
395         }
396         if (myTeam == null) {
397             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
398         }
399 
400         try {
401             // Record parallel team.
402             theLoop.myTeam = this.myTeam;
403 
404             // Get current parallel team thread.
405             ParallelTeamThread currentThread = getCurrentThread();
406             int currentIndex = currentThread.myIndex;
407 
408             // Do top-of-parallel-construct processing.
409             IntegerSchedule schedule = null;
410             if (currentThread.arriveAtParallelConstruct()) {
411                 // First thread to arrive sets up the shared parallel for loop
412                 // schedule object and stores it (or an exception if any) in
413                 // each team thread.
414                 try {
415                     schedule = theLoop.schedule();
416                     schedule.commonStart(myTeam.K, new Range(first, last, stride));
417                     for (ParallelTeamThread thread : myTeam.myThread) {
418                         thread.setIntegerSchedule(schedule);
419                     }
420                 } catch (Throwable exc) {
421                     for (ParallelTeamThread thread : myTeam.myThread) {
422                         thread.setConstructException(exc);
423                     }
424                 }
425             }
426 
427             // Get the shared parallel for loop schedule object.
428             schedule = currentThread.getIntegerSchedule();
429             theLoop.mySchedule = schedule;
430 
431             // Prepare to catch exceptions thrown by the parallel for loop body.
432             Throwable runException = null;
433             try {
434                 // Perform per-thread initialization.
435                 theLoop.start();
436 
437                 // Repeatedly get and process a chunk of loop iterations.
438                 Range chunk;
439                 while ((chunk = schedule.commonNext(currentIndex)) != null) {
440                     theLoop.commonRun(chunk.lb(), chunk.ub(), chunk.stride());
441                 }
442 
443                 // Perform per-thread finalization.
444                 theLoop.finish();
445             } catch (Throwable exc) {
446                 runException = exc;
447                 schedule.myBreak = true;
448             }
449 
450             // Barrier synchronization.
451             action.doBarrier(currentThread);
452 
453             // Propagate any exception thrown by the run() method.
454             ParallelTeam.rethrow(runException);
455         } finally {
456             // Forget parallel team.
457             theLoop.myTeam = null;
458             theLoop.mySchedule = null;
459         }
460     }
461 
462     /**
463      * Execute a parallel for loop within this parallel region. For further
464      * information, see class {@linkplain LongForLoop}. The loop index goes from
465      * <code>first</code> (inclusive) to <code>last</code> (inclusive) in steps of +1.
466      * If <code>first</code> is greater than <code>last</code>, then no loop iterations
467      * are performed. At the end of the parallel for loop, the parallel team
468      * threads wait for each other at a barrier.
469      * <P>
470      * <I>Note:</I> Either all threads in the parallel team must call the
471      * <code>execute()</code> method with identical arguments, or none of the
472      * threads must call the <code>execute()</code> method.
473      *
474      * @param first First loop index.
475      * @param last Last loop index.
476      * @param theLoop Parallel for loop.
477      * @exception NullPointerException (unchecked exception) Thrown if
478      * <code>theLoop</code> is null.
479      * @exception IllegalStateException (unchecked exception) Thrown if no
480      * parallel team is executing this parallel region.
481      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
482      * an exception.
483      * @throws java.lang.Exception if any.
484      */
485     public final void execute(long first,
486             long last,
487             LongForLoop theLoop)
488             throws Exception {
489         execute(first, last, theLoop, BarrierAction.WAIT);
490     }
491 
492     /**
493      * Execute a parallel for loop within this parallel region. For further
494      * information, see class {@linkplain LongForLoop}. The loop index goes from
495      * <code>first</code> (inclusive) to <code>last</code> (inclusive) in steps of +1.
496      * If <code>first</code> is greater than <code>last</code>, then no loop iterations
497      * are performed. At the end of the parallel for loop, the parallel team
498      * threads encounter a barrier, and their behavior depends on the given
499      * {@linkplain BarrierAction}.
500      * <P>
501      * <I>Note:</I> Either all threads in the parallel team must call the
502      * <code>execute()</code> method with identical arguments, or none of the
503      * threads must call the <code>execute()</code> method.
504      *
505      * @param first First loop index.
506      * @param last Last loop index.
507      * @param theLoop Parallel for loop.
508      * @param action Barrier action.
509      * @exception NullPointerException (unchecked exception) Thrown if
510      * <code>theLoop</code> is null. Thrown if
511      * <code>action</code> is null.
512      * @exception IllegalStateException (unchecked exception) Thrown if no
513      * parallel team is executing this parallel region.
514      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
515      * an exception.
516      * @throws java.lang.Exception if any.
517      */
518     public final void execute(long first,
519             long last,
520             LongForLoop theLoop,
521             BarrierAction action)
522             throws Exception {
523         // Verify preconditions.
524         if (theLoop == null) {
525             throw new NullPointerException("ParallelRegion.execute(): Parallel for loop is null");
526         }
527         if (action == null) {
528             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
529         }
530         if (myTeam == null) {
531             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
532         }
533 
534         try {
535             // Record parallel team.
536             theLoop.myTeam = this.myTeam;
537 
538             // Get current parallel team thread.
539             ParallelTeamThread currentThread = getCurrentThread();
540             int currentIndex = currentThread.myIndex;
541 
542             // Do top-of-parallel-construct processing.
543             LongSchedule schedule = null;
544             if (currentThread.arriveAtParallelConstruct()) {
545                 // First thread to arrive sets up the shared parallel for loop
546                 // schedule object and stores it (or an exception if any) in
547                 // each team thread.
548                 try {
549                     schedule = theLoop.schedule();
550                     schedule.commonStart(myTeam.K, new LongRange(first, last));
551                     for (ParallelTeamThread thread : myTeam.myThread) {
552                         thread.setLongSchedule(schedule);
553                     }
554                 } catch (Throwable exc) {
555                     for (ParallelTeamThread thread : myTeam.myThread) {
556                         thread.setConstructException(exc);
557                     }
558                 }
559             }
560 
561             // Get the shared parallel for loop schedule object.
562             schedule = currentThread.getLongSchedule();
563             theLoop.mySchedule = schedule;
564 
565             // Prepare to catch exceptions thrown by the parallel for loop body.
566             Throwable runException = null;
567             try {
568                 // Perform per-thread initialization.
569                 theLoop.start();
570 
571                 // Repeatedly get and process a chunk of loop iterations.
572                 LongRange chunk;
573                 while ((chunk = schedule.commonNext(currentIndex)) != null) {
574                     theLoop.commonRun(chunk.lb(), chunk.ub());
575                 }
576 
577                 // Perform per-thread finalization.
578                 theLoop.finish();
579             } catch (Throwable exc) {
580                 runException = exc;
581                 schedule.myBreak = true;
582             }
583 
584             // Barrier synchronization.
585             action.doBarrier(currentThread);
586 
587             // Propagate any exception thrown by the run() method.
588             ParallelTeam.rethrow(runException);
589         } finally {
590             // Forget parallel team.
591             theLoop.myTeam = null;
592             theLoop.mySchedule = null;
593         }
594     }
595 
596     /**
597      * Execute a parallel for loop within this parallel region. For further
598      * information, see class {@linkplain LongStrideForLoop}. The loop index
599      * goes from <code>first</code> (inclusive) to <code>last</code> (inclusive) in
600      * steps of <code>stride</code>. The stride must be positive. If <code>first</code>
601      * is greater than <code>last</code>, then no loop iterations are performed. At
602      * the end of the parallel for loop, the parallel team threads wait for each
603      * other at a barrier.
604      * <P>
605      * <I>Note:</I> Either all threads in the parallel team must call the
606      * <code>execute()</code> method with identical arguments, or none of the
607      * threads must call the <code>execute()</code> method.
608      *
609      * @param first First loop index.
610      * @param last Last loop index.
611      * @param stride Loop index stride, &gt;= 1.
612      * @param theLoop Parallel for loop.
613      * @exception IllegalArgumentException (unchecked exception) Thrown if
614      * <code>stride</code> &lt; 1.
615      * @exception NullPointerException (unchecked exception) Thrown if
616      * <code>theLoop</code> is null.
617      * @exception IllegalStateException (unchecked exception) Thrown if no
618      * parallel team is executing this parallel region.
619      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
620      * an exception.
621      * @throws java.lang.Exception if any.
622      */
623     public final void execute(long first,
624             long last,
625             long stride,
626             LongStrideForLoop theLoop)
627             throws Exception {
628         execute(first, last, stride, theLoop, BarrierAction.WAIT);
629     }
630 
631     /**
632      * Execute a parallel for loop within this parallel region. For further
633      * information, see class {@linkplain LongStrideForLoop}. The loop index
634      * goes from <code>first</code> (inclusive) to <code>last</code> (inclusive) in
635      * steps of <code>stride</code>. The stride must be positive. If <code>first</code>
636      * is greater than <code>last</code>, then no loop iterations are performed. At
637      * the end of the parallel for loop, the parallel team threads encounter a
638      * barrier, and their behavior depends on the given {@linkplain
639      * BarrierAction}.
640      * <P>
641      * <I>Note:</I> Either all threads in the parallel team must call the
642      * <code>execute()</code> method with identical arguments, or none of the
643      * threads must call the <code>execute()</code> method.
644      *
645      * @param first First loop index.
646      * @param last Last loop index.
647      * @param stride Loop index stride, &gt;= 1.
648      * @param theLoop Parallel for loop.
649      * @param action Barrier action.
650      * @exception IllegalArgumentException (unchecked exception) Thrown if
651      * <code>stride</code> &lt; 1.
652      * @exception NullPointerException (unchecked exception) Thrown if
653      * <code>theLoop</code> is null. Thrown if
654      * <code>action</code> is null.
655      * @exception IllegalStateException (unchecked exception) Thrown if no
656      * parallel team is executing this parallel region.
657      * @exception Exception Thrown if one of <code>theLoop</code>'s methods throws
658      * an exception.
659      * @throws java.lang.Exception if any.
660      */
661     public final void execute(long first,
662             long last,
663             long stride,
664             LongStrideForLoop theLoop,
665             BarrierAction action)
666             throws Exception {
667         // Verify preconditions.
668         if (stride <= 0) {
669             throw new IllegalArgumentException("ParallelRegion.execute(): Stride = " + stride + " illegal");
670         }
671         if (theLoop == null) {
672             throw new NullPointerException("ParallelRegion.execute(): Parallel for loop is null");
673         }
674         if (action == null) {
675             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
676         }
677         if (myTeam == null) {
678             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
679         }
680 
681         try {
682             // Record parallel team.
683             theLoop.myTeam = this.myTeam;
684 
685             // Get current parallel team thread.
686             ParallelTeamThread currentThread = getCurrentThread();
687             int currentIndex = currentThread.myIndex;
688 
689             // Do top-of-parallel-construct processing.
690             LongSchedule schedule = null;
691             if (currentThread.arriveAtParallelConstruct()) {
692                 // First thread to arrive sets up the shared parallel for loop
693                 // schedule object and stores it (or an exception if any) in
694                 // each team thread.
695                 try {
696                     schedule = theLoop.schedule();
697                     schedule.commonStart(myTeam.K, new LongRange(first, last, stride));
698                     for (ParallelTeamThread thread : myTeam.myThread) {
699                         thread.setLongSchedule(schedule);
700                     }
701                 } catch (Throwable exc) {
702                     for (ParallelTeamThread thread : myTeam.myThread) {
703                         thread.setConstructException(exc);
704                     }
705                 }
706             }
707 
708             // Get the shared parallel for loop schedule object.
709             schedule = currentThread.getLongSchedule();
710             theLoop.mySchedule = schedule;
711 
712             // Prepare to catch exceptions thrown by the parallel for loop body.
713             Throwable runException = null;
714             try {
715                 // Perform per-thread initialization.
716                 theLoop.start();
717 
718                 // Repeatedly get and process a chunk of loop iterations.
719                 LongRange chunk;
720                 while ((chunk = schedule.commonNext(currentIndex)) != null) {
721                     theLoop.commonRun(chunk.lb(), chunk.ub(), chunk.stride());
722                 }
723 
724                 // Perform per-thread finalization.
725                 theLoop.finish();
726             } catch (Throwable exc) {
727                 runException = exc;
728                 schedule.myBreak = true;
729             }
730 
731             // Barrier synchronization.
732             action.doBarrier(currentThread);
733 
734             // Propagate any exception thrown by the run() method.
735             ParallelTeam.rethrow(runException);
736         } finally {
737             // Forget parallel team.
738             theLoop.myTeam = null;
739             theLoop.mySchedule = null;
740         }
741     }
742 
743     /**
744      * Execute a parallel iteration within this parallel region. For further
745      * information, see class {@linkplain ParallelIteration}. The items
746      * processed by the iteration are the elements of the given array. The
747      * iteration order is from index 0 upwards. At the end of the parallel
748      * iteration, the parallel team threads wait for each other at a barrier.
749      * <P>
750      * <I>Note:</I> Either all threads in the parallel team must call the
751      * <code>execute()</code> method with identical arguments, or none of the
752      * threads must call the <code>execute()</code> method.
753      *
754      * @param <T> Data type of the items iterated over.
755      * @param theArray Array containing the items.
756      * @param theIteration Parallel iteration.
757      * @exception NullPointerException (unchecked exception) Thrown if
758      * <code>theArray</code> is null or
759      * <code>theIteration</code> is null.
760      * @exception IllegalStateException (unchecked exception) Thrown if no
761      * parallel team is executing this parallel region.
762      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
763      * throws an exception.
764      * @throws java.lang.Exception if any.
765      */
766     public final <T> void execute(T[] theArray,
767             ParallelIteration<T> theIteration)
768             throws Exception {
769         execute(theArray, theIteration, BarrierAction.WAIT);
770     }
771 
772     /**
773      * Suppress warnings for casts of ItemGenerator.
774      * @param obj The ItemGenerator instance.
775      * @param <T> Data type of the items iterated over.
776      * @return
777      */
778     @SuppressWarnings("unchecked")
779     private static <T> ItemGenerator<T> castItemGenerator(Object obj) {
780         return (ItemGenerator<T>) obj;
781     }
782 
783     /**
784      * Execute a parallel iteration within this parallel region. For further
785      * information, see class {@linkplain ParallelIteration}. The items
786      * processed by the iteration are the elements of the given array. The
787      * iteration order is from index 0 upwards. At the end of the parallel
788      * iteration, the parallel team threads encounter a barrier, and their
789      * behavior depends on the given {@linkplain BarrierAction}.
790      * <P>
791      * <I>Note:</I> Either all threads in the parallel team must call the
792      * <code>execute()</code> method with identical arguments, or none of the
793      * threads must call the <code>execute()</code> method.
794      *
795      * @param <T> Data type of the items iterated over.
796      * @param theArray Array containing the items.
797      * @param theIteration Parallel iteration.
798      * @param action Barrier action.
799      * @exception NullPointerException (unchecked exception) Thrown if
800      * <code>theArray</code> is null. Thrown if
801      * <code>theIteration</code> is null. Thrown if <code>action</code> is null.
802      * @exception IllegalStateException (unchecked exception) Thrown if no
803      * parallel team is executing this parallel region.
804      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
805      * throws an exception.
806      * @throws java.lang.Exception if any.
807      */
808     public final <T> void execute(T[] theArray,
809             ParallelIteration<T> theIteration,
810             BarrierAction action)
811             throws Exception {
812         // Verify preconditions.
813         if (theArray == null) {
814             throw new NullPointerException("ParallelRegion.execute(): Array is null");
815         }
816         if (theIteration == null) {
817             throw new NullPointerException("ParallelRegion.execute(): Parallel iteration is null");
818         }
819         if (action == null) {
820             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
821         }
822         if (myTeam == null) {
823             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
824         }
825 
826         try {
827             // Record parallel team.
828             theIteration.myTeam = this.myTeam;
829 
830             // Get current parallel team thread.
831             ParallelTeamThread currentThread = getCurrentThread();
832 
833             // Do top-of-parallel-construct processing.
834             ItemGenerator<T> generator = null;
835             if (currentThread.arriveAtParallelConstruct()) {
836                 // First thread to arrive sets up the shared item generator
837                 // object and stores it (or an exception if any) in each team
838                 // thread.
839                 try {
840                     generator = new ArrayItemGenerator<T>(theArray);
841                     for (ParallelTeamThread thread : myTeam.myThread) {
842                         thread.setItemGenerator(generator);
843                     }
844                 } catch (Throwable exc) {
845                     for (ParallelTeamThread thread : myTeam.myThread) {
846                         thread.setConstructException(exc);
847                     }
848                 }
849             }
850 
851             // Get the shared item generator object.
852             generator = castItemGenerator(currentThread.getItemGenerator());
853             theIteration.myItemGenerator = generator;
854 
855             // Prepare to catch exceptions thrown by the parallel iteration
856             // body.
857             Throwable runException = null;
858             try {
859                 // Perform per-thread initialization.
860                 theIteration.start();
861 
862                 // Repeatedly get and process an item.
863                 ItemHolder<T> itemholder;
864                 while ((itemholder = generator.nextItem()) != null) {
865                     theIteration.commonRun(itemholder.mySequenceNumber, itemholder.myItem);
866                 }
867 
868                 // Perform per-thread finalization.
869                 theIteration.finish();
870             } catch (Throwable exc) {
871                 runException = exc;
872                 generator.myBreak = true;
873             }
874 
875             // Barrier synchronization.
876             action.doBarrier(currentThread);
877 
878             // Propagate any exception thrown by the run() method.
879             ParallelTeam.rethrow(runException);
880         } finally {
881             // Forget parallel team.
882             theIteration.myTeam = null;
883             theIteration.myItemGenerator = null;
884         }
885     }
886 
887     /**
888      * Execute a parallel iteration within this parallel region. For further
889      * information, see class {@linkplain ParallelIteration}. The items
890      * processed by the iteration are the items returned by the given iterator.
891      * The iteration order is that of the given iterator. At the end of the
892      * parallel iteration, the parallel team threads wait for each other at a
893      * barrier.
894      * <P>
895      * <I>Note:</I> Either all threads in the parallel team must call the
896      * <code>execute()</code> method with identical arguments, or none of the
897      * threads must call the <code>execute()</code> method.
898      *
899      * @param <T> Data type of the items iterated over.
900      * @param theIterator Iterator over the items.
901      * @param theIteration Parallel iteration.
902      * @exception NullPointerException (unchecked exception) Thrown if
903      * <code>theIterator</code> is null or
904      * <code>theIteration</code> is null.
905      * @exception IllegalStateException (unchecked exception) Thrown if no
906      * parallel team is executing this parallel region.
907      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
908      * throws an exception.
909      * @throws java.lang.Exception if any.
910      */
911     public final <T> void execute(Iterator<T> theIterator,
912             ParallelIteration<T> theIteration)
913             throws Exception {
914         execute(theIterator, theIteration, BarrierAction.WAIT);
915     }
916 
917     /**
918      * Execute a parallel iteration within this parallel region. For further
919      * information, see class {@linkplain ParallelIteration}. The items
920      * processed by the iteration are the items returned by the given iterator.
921      * The iteration order is that of the given iterator. At the end of the
922      * parallel iteration, the parallel team threads encounter a barrier, and
923      * their behavior depends on the given {@linkplain BarrierAction}.
924      * <P>
925      * <I>Note:</I> Either all threads in the parallel team must call the
926      * <code>execute()</code> method with identical arguments, or none of the
927      * threads must call the <code>execute()</code> method.
928      *
929      * @param <T> Data type of the items iterated over.
930      * @param theIterator Iterator over the items.
931      * @param theIteration Parallel iteration.
932      * @param action Barrier action.
933      * @exception NullPointerException (unchecked exception) Thrown if
934      * <code>theIterator</code> is null. Thrown if <code>theIteration</code> is null.
935      * Thrown if <code>action</code> is null.
936      * @exception IllegalStateException (unchecked exception) Thrown if no
937      * parallel team is executing this parallel region.
938      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
939      * throws an exception.
940      * @throws java.lang.Exception if any.
941      */
942     public final <T> void execute(Iterator<T> theIterator,
943             ParallelIteration<T> theIteration,
944             BarrierAction action)
945             throws Exception {
946         // Verify preconditions.
947         if (theIterator == null) {
948             throw new NullPointerException("ParallelRegion.execute(): Iterator is null");
949         }
950         if (theIteration == null) {
951             throw new NullPointerException("ParallelRegion.execute(): Parallel iteration is null");
952         }
953         if (action == null) {
954             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
955         }
956         if (myTeam == null) {
957             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
958         }
959 
960         try {
961             // Record parallel team.
962             theIteration.myTeam = this.myTeam;
963 
964             // Get current parallel team thread.
965             ParallelTeamThread currentThread = getCurrentThread();
966 
967             // Do top-of-parallel-construct processing.
968             ItemGenerator<T> generator = null;
969             if (currentThread.arriveAtParallelConstruct()) {
970                 // First thread to arrive sets up the shared item generator
971                 // object and stores it (or an exception if any) in each team
972                 // thread.
973                 try {
974                     generator = new IteratorItemGenerator<T>(theIterator);
975                     for (ParallelTeamThread thread : myTeam.myThread) {
976                         thread.setItemGenerator(generator);
977                     }
978                 } catch (Throwable exc) {
979                     for (ParallelTeamThread thread : myTeam.myThread) {
980                         thread.setConstructException(exc);
981                     }
982                 }
983             }
984 
985             // Get the shared item generator object.
986             generator = castItemGenerator(currentThread.getItemGenerator());
987             theIteration.myItemGenerator = generator;
988 
989             // Prepare to catch exceptions thrown by the parallel iteration
990             // body.
991             Throwable runException = null;
992             try {
993                 // Perform per-thread initialization.
994                 theIteration.start();
995 
996                 // Repeatedly get and process an item.
997                 ItemHolder<T> itemholder;
998                 while ((itemholder = generator.nextItem()) != null) {
999                     theIteration.commonRun(itemholder.mySequenceNumber, itemholder.myItem);
1000                 }
1001 
1002                 // Perform per-thread finalization.
1003                 theIteration.finish();
1004             } catch (Throwable exc) {
1005                 runException = exc;
1006                 generator.myBreak = true;
1007             }
1008 
1009             // Barrier synchronization.
1010             action.doBarrier(currentThread);
1011 
1012             // Propagate any exception thrown by the run() method.
1013             ParallelTeam.rethrow(runException);
1014         } finally {
1015             // Forget parallel team.
1016             theIteration.myTeam = null;
1017             theIteration.myItemGenerator = null;
1018         }
1019     }
1020 
1021     /**
1022      * Execute a parallel iteration within this parallel region. For further
1023      * information, see class {@linkplain ParallelIteration}. The items
1024      * processed by the iteration are the items contained in the given iterable
1025      * collection. The iteration order is that of the given iterable
1026      * collection's iterator. At the end of the parallel iteration, the parallel
1027      * team threads wait for each other at a barrier.
1028      * <P>
1029      * <I>Note:</I> Either all threads in the parallel team must call the
1030      * <code>execute()</code> method with identical arguments, or none of the
1031      * threads must call the <code>execute()</code> method.
1032      *
1033      * @param <T> Data type of the items iterated over.
1034      * @param theIterable Iterable collection containing the items.
1035      * @param theIteration Parallel iteration.
1036      * @exception NullPointerException (unchecked exception) Thrown if
1037      * <code>theIterable</code> is null or
1038      * <code>theIteration</code> is null.
1039      * @exception IllegalStateException (unchecked exception) Thrown if no
1040      * parallel team is executing this parallel region.
1041      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
1042      * throws an exception.
1043      * @throws java.lang.Exception if any.
1044      */
1045     public final <T> void execute(Iterable<T> theIterable,
1046             ParallelIteration<T> theIteration)
1047             throws Exception {
1048         execute(theIterable, theIteration, BarrierAction.WAIT);
1049     }
1050 
1051     /**
1052      * Execute a parallel iteration within this parallel region. For further
1053      * information, see class {@linkplain ParallelIteration}. The items
1054      * processed by the iteration are the items contained in the given iterable
1055      * collection. The iteration order is that of the given iterable
1056      * collection's iterator. At the end of the parallel iteration, the parallel
1057      * team threads encounter a barrier, and their behavior depends on the given
1058      * {@linkplain BarrierAction}.
1059      * <P>
1060      * <I>Note:</I> Either all threads in the parallel team must call the
1061      * <code>execute()</code> method with identical arguments, or none of the
1062      * threads must call the <code>execute()</code> method.
1063      *
1064      * @param <T> Data type of the items iterated over.
1065      * @param theIterable Iterable collection containing the items.
1066      * @param theIteration Parallel iteration.
1067      * @param action Barrier action.
1068      * @exception NullPointerException (unchecked exception) Thrown if
1069      * <code>theIterable</code> is null. Thrown if <code>theIteration</code> is null.
1070      * Thrown if <code>action</code> is null.
1071      * @exception IllegalStateException (unchecked exception) Thrown if no
1072      * parallel team is executing this parallel region.
1073      * @exception Exception Thrown if one of <code>theIteration</code>'s methods
1074      * throws an exception.
1075      * @throws java.lang.Exception if any.
1076      */
1077     public final <T> void execute(Iterable<T> theIterable,
1078             ParallelIteration<T> theIteration,
1079             BarrierAction action)
1080             throws Exception {
1081         // Verify preconditions.
1082         if (theIterable == null) {
1083             throw new NullPointerException("ParallelRegion.execute(): Iterable collection is null");
1084         }
1085         if (theIteration == null) {
1086             throw new NullPointerException("ParallelRegion.execute(): Parallel iteration is null");
1087         }
1088         if (action == null) {
1089             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
1090         }
1091         if (myTeam == null) {
1092             throw new IllegalStateException("ParallelRegion.execute(): No parallel team executing");
1093         }
1094 
1095         try {
1096             // Record parallel team.
1097             theIteration.myTeam = this.myTeam;
1098 
1099             // Get current parallel team thread.
1100             ParallelTeamThread currentThread = getCurrentThread();
1101 
1102             // Do top-of-parallel-construct processing.
1103             ItemGenerator<T> generator = null;
1104             if (currentThread.arriveAtParallelConstruct()) {
1105                 // First thread to arrive sets up the shared item generator
1106                 // object and stores it (or an exception if any) in each team
1107                 // thread.
1108                 try {
1109                     generator
1110                             = new IteratorItemGenerator<T>(theIterable.iterator());
1111                     for (ParallelTeamThread thread : myTeam.myThread) {
1112                         thread.setItemGenerator(generator);
1113                     }
1114                 } catch (Throwable exc) {
1115                     for (ParallelTeamThread thread : myTeam.myThread) {
1116                         thread.setConstructException(exc);
1117                     }
1118                 }
1119             }
1120 
1121             // Get the shared item generator object.
1122             generator = castItemGenerator(currentThread.getItemGenerator());
1123             theIteration.myItemGenerator = generator;
1124 
1125             // Prepare to catch exceptions thrown by the parallel iteration
1126             // body.
1127             Throwable runException = null;
1128             try {
1129                 // Perform per-thread initialization.
1130                 theIteration.start();
1131 
1132                 // Repeatedly get and process an item.
1133                 ItemHolder<T> itemholder;
1134                 while ((itemholder = generator.nextItem()) != null) {
1135                     theIteration.commonRun(itemholder.mySequenceNumber, itemholder.myItem);
1136                 }
1137 
1138                 // Perform per-thread finalization.
1139                 theIteration.finish();
1140             } catch (Throwable exc) {
1141                 runException = exc;
1142                 generator.myBreak = true;
1143             }
1144 
1145             // Barrier synchronization.
1146             action.doBarrier(currentThread);
1147 
1148             // Propagate any exception thrown by the run() method.
1149             ParallelTeam.rethrow(runException);
1150         } finally {
1151             // Forget parallel team.
1152             theIteration.myTeam = null;
1153             theIteration.myItemGenerator = null;
1154         }
1155     }
1156 
1157     /**
1158      * Execute a parallel section within this parallel region. The parallel
1159      * section's <code>run()</code> method is called by one of the parallel team
1160      * threads. For further information, see class {@linkplain ParallelSection}.
1161      * At the end of the parallel section, the parallel team threads wait for
1162      * each other at a barrier.
1163      * <P>
1164      * <I>Note:</I> Either all threads in the parallel team must call the
1165      * <code>execute()</code> method with identical arguments, or none of the
1166      * threads must call the <code>execute()</code> method.
1167      *
1168      * @param section Parallel section.
1169      * @exception NullPointerException (unchecked exception) Thrown if
1170      * <code>section</code> is null.
1171      * @exception IllegalStateException (unchecked exception) Thrown if no
1172      * parallel team is executing this parallel region.
1173      * @exception Exception Thrown if the parallel section's <code>run()</code>
1174      * method throws an exception.
1175      * @throws java.lang.Exception if any.
1176      */
1177     public final void execute(ParallelSection section)
1178             throws Exception {
1179         execute(new ParallelSection[]{section}, BarrierAction.WAIT);
1180     }
1181 
1182     /**
1183      * Execute a parallel section within this parallel region. The parallel
1184      * section's <code>run()</code> method is called by one of the parallel team
1185      * threads. For further information, see class {@linkplain ParallelSection}.
1186      * At the end of the parallel section, the parallel team threads encounter a
1187      * barrier, and their behavior depends on the given {@linkplain
1188      * BarrierAction}.
1189      * <P>
1190      * <I>Note:</I> Either all threads in the parallel team must call the
1191      * <code>execute()</code> method with identical arguments, or none of the
1192      * threads must call the <code>execute()</code> method.
1193      *
1194      * @param section Parallel section.
1195      * @param action Barrier action.
1196      * @exception NullPointerException (unchecked exception) Thrown if
1197      * <code>section</code> is null. Thrown if
1198      * <code>action</code> is null.
1199      * @exception IllegalStateException (unchecked exception) Thrown if no
1200      * parallel team is executing this parallel region.
1201      * @exception Exception Thrown if the parallel section's <code>run()</code>
1202      * method throws an exception.
1203      * @throws java.lang.Exception if any.
1204      */
1205     public final void execute(ParallelSection section,
1206             BarrierAction action)
1207             throws Exception {
1208         execute(new ParallelSection[]{section}, action);
1209     }
1210 
1211     /**
1212      * Execute a group of two parallel sections concurrently within this
1213      * parallel region. Each parallel section's <code>run()</code> method is called
1214      * by a different parallel team thread. For further information, see class
1215      * {@linkplain ParallelSection}. At the end of the parallel section group,
1216      * the parallel team threads wait for each other at a barrier.
1217      * <P>
1218      * <I>Note:</I> Either all threads in the parallel team must call the
1219      * <code>execute()</code> method with identical arguments, or none of the
1220      * threads must call the <code>execute()</code> method.
1221      *
1222      * @param section1 First parallel section.
1223      * @param section2 Second parallel section.
1224      * @exception NullPointerException (unchecked exception) Thrown if
1225      * <code>section1</code> is null. Thrown if
1226      * <code>section2</code> is null.
1227      * @exception IllegalStateException (unchecked exception) Thrown if no
1228      * parallel team is executing this parallel region.
1229      * @exception Exception Thrown if one of the parallel sections'
1230      * <code>run()</code> methods throws an exception.
1231      * @throws java.lang.Exception if any.
1232      */
1233     public final void execute(ParallelSection section1,
1234             ParallelSection section2)
1235             throws Exception {
1236         execute(new ParallelSection[]{section1, section2},
1237                 BarrierAction.WAIT);
1238     }
1239 
1240     /**
1241      * Execute a group of two parallel sections concurrently within this
1242      * parallel region. Each parallel section's <code>run()</code> method is called
1243      * by a different parallel team thread. For further information, see class
1244      * {@linkplain ParallelSection}. At the end of the parallel section group,
1245      * the parallel team threads encounter a barrier, and their behavior depends
1246      * on the given {@linkplain BarrierAction}.
1247      * <P>
1248      * <I>Note:</I> Either all threads in the parallel team must call the
1249      * <code>execute()</code> method with identical arguments, or none of the
1250      * threads must call the <code>execute()</code> method.
1251      *
1252      * @param section1 First parallel section.
1253      * @param section2 Second parallel section.
1254      * @param action Barrier action.
1255      * @exception NullPointerException (unchecked exception) Thrown if
1256      * <code>section1</code> is null. Thrown if
1257      * <code>section2</code> is null. Thrown if <code>action</code> is null.
1258      * @exception IllegalStateException (unchecked exception) Thrown if no
1259      * parallel team is executing this parallel region.
1260      * @exception Exception Thrown if one of the parallel sections'
1261      * <code>run()</code> methods throws an exception.
1262      * @throws java.lang.Exception if any.
1263      */
1264     public final void execute(ParallelSection section1,
1265             ParallelSection section2,
1266             BarrierAction action)
1267             throws Exception {
1268         execute(new ParallelSection[]{section1, section2},
1269                 action);
1270     }
1271 
1272     /**
1273      * Execute a group of three parallel sections concurrently within this
1274      * parallel region. Each parallel section's <code>run()</code> method is called
1275      * by a different parallel team thread. For further information, see class
1276      * {@linkplain ParallelSection}. At the end of the parallel section group,
1277      * the parallel team threads wait for each other at a barrier.
1278      * <P>
1279      * <I>Note:</I> Either all threads in the parallel team must call the
1280      * <code>execute()</code> method with identical arguments, or none of the
1281      * threads must call the <code>execute()</code> method.
1282      *
1283      * @param section1 First parallel section.
1284      * @param section2 Second parallel section.
1285      * @param section3 Third parallel section.
1286      * @exception NullPointerException (unchecked exception) Thrown if
1287      * <code>section1</code> is null. Thrown if
1288      * <code>section2</code> is null. Thrown if <code>section3</code> is null.
1289      * @exception IllegalStateException (unchecked exception) Thrown if no
1290      * parallel team is executing this parallel region.
1291      * @exception Exception Thrown if one of the parallel sections'
1292      * <code>run()</code> methods throws an exception.
1293      * @throws java.lang.Exception if any.
1294      */
1295     public final void execute(ParallelSection section1,
1296             ParallelSection section2,
1297             ParallelSection section3)
1298             throws Exception {
1299         execute(new ParallelSection[]{section1, section2, section3},
1300                 BarrierAction.WAIT);
1301     }
1302 
1303     /**
1304      * Execute a group of three parallel sections concurrently within this
1305      * parallel region. Each parallel section's <code>run()</code> method is called
1306      * by a different parallel team thread. For further information, see class
1307      * {@linkplain ParallelSection}. At the end of the parallel section group,
1308      * the parallel team threads encounter a barrier, and their behavior depends
1309      * on the given {@linkplain BarrierAction}.
1310      * <P>
1311      * <I>Note:</I> Either all threads in the parallel team must call the
1312      * <code>execute()</code> method with identical arguments, or none of the
1313      * threads must call the <code>execute()</code> method.
1314      *
1315      * @param section1 First parallel section.
1316      * @param section2 Second parallel section.
1317      * @param section3 Third parallel section.
1318      * @param action Barrier action.
1319      * @exception NullPointerException (unchecked exception) Thrown if
1320      * <code>section1</code> is null. Thrown if
1321      * <code>section2</code> is null. Thrown if <code>section3</code> is null. Thrown if
1322      * <code>action</code> is null.
1323      * @exception IllegalStateException (unchecked exception) Thrown if no
1324      * parallel team is executing this parallel region.
1325      * @exception Exception Thrown if one of the parallel sections'
1326      * <code>run()</code> methods throws an exception.
1327      * @throws java.lang.Exception if any.
1328      */
1329     public final void execute(ParallelSection section1,
1330             ParallelSection section2,
1331             ParallelSection section3,
1332             BarrierAction action)
1333             throws Exception {
1334         execute(new ParallelSection[]{section1, section2, section3},
1335                 action);
1336     }
1337 
1338     /**
1339      * Execute a group of parallel sections concurrently within this parallel
1340      * region. Each parallel section's <code>run()</code> method is called by a
1341      * different parallel team thread. For further information, see class
1342      * {@linkplain ParallelSection}. At the end of the parallel section group,
1343      * the parallel team threads wait for each other at a barrier.
1344      * <P>
1345      * <I>Note:</I> Either all threads in the parallel team must call the
1346      * <code>execute()</code> method with identical arguments, or none of the
1347      * threads must call the <code>execute()</code> method.
1348      *
1349      * @param sections Parallel sections.
1350      * @exception NullPointerException (unchecked exception) Thrown if any of
1351      * the <code>sections</code> is null.
1352      * @exception IllegalStateException (unchecked exception) Thrown if no
1353      * parallel team is executing this parallel region.
1354      * @exception Exception Thrown if one of the parallel sections'
1355      * <code>run()</code> methods throws an exception.
1356      * @throws java.lang.Exception if any.
1357      */
1358     public final void execute(ParallelSection[] sections)
1359             throws Exception {
1360         execute(sections, BarrierAction.WAIT);
1361     }
1362 
1363     /**
1364      * Execute a group of parallel sections concurrently within this parallel
1365      * region. Each parallel section's <code>run()</code> method is called by a
1366      * different parallel team thread. For further information, see class
1367      * {@linkplain ParallelSection}. At the end of the parallel section group,
1368      * the parallel team threads encounter a barrier, and their behavior depends
1369      * on the given {@linkplain BarrierAction}.
1370      * <P>
1371      * <I>Note:</I> Either all threads in the parallel team must call the
1372      * <code>execute()</code> method with identical arguments, or none of the
1373      * threads must call the <code>execute()</code> method.
1374      *
1375      * @param sections Parallel sections.
1376      * @param action Barrier action.
1377      * @exception NullPointerException (unchecked exception) Thrown if any of
1378      * the <code>sections</code> is null. Thrown if <code>action</code> is null.
1379      * @exception IllegalStateException (unchecked exception) Thrown if no
1380      * parallel team is executing this parallel region.
1381      * @exception Exception Thrown if one of the parallel sections'
1382      * <code>run()</code> methods throws an exception.
1383      * @throws java.lang.Exception if any.
1384      */
1385     public final void execute(ParallelSection[] sections,
1386             BarrierAction action)
1387             throws Exception {
1388         if (sections == null) {
1389             throw new NullPointerException("ParallelRegion.execute(): sections is null");
1390         }
1391         for (ParallelSection section : sections) {
1392             if (section == null) {
1393                 throw new NullPointerException("ParallelRegion.execute(): A parallel section is null");
1394             }
1395         }
1396         if (action == null) {
1397             throw new NullPointerException("ParallelRegion.execute(): Barrier action is null");
1398         }
1399 
1400         execute(sections, new ParallelIteration<ParallelSection>() {
1401             public void run(ParallelSection section) throws Exception {
1402                 try {
1403                     section.myTeam = this.myTeam;
1404                     section.run();
1405                 } finally {
1406                     section.myTeam = null;
1407                 }
1408             }
1409         },
1410                 action);
1411     }
1412 
1413     /**
1414      * Perform a section of code in a critical region with exclusive locking.
1415      * The locking is performed using the default lock, a hidden {@linkplain
1416      * Lock} variable shared by all the parallel team threads. The thread
1417      * calling the <code>critical()</code> method waits until no other thread is
1418      * executing a critical region with exclusive locking using the default lock
1419      * and no other thread is executing a critical region with nonexclusive
1420      * locking using the default lock. The thread then calls
1421      * <code>theSection</code>'s <code>run()</code> method with exclusive locking using
1422      * the default lock. When the <code>run()</code> method returns, the thread
1423      * unlocks the lock and returns from the <code>critical()</code> method.
1424      * <P>
1425      * If the parallel section's <code>run()</code> method throws an exception, the
1426      * <code>critical()</code> method throws that same exception in the thread that
1427      * called the <code>run()</code> method (after unlocking the lock).
1428      *
1429      * @param theSection Parallel section to execute in the critical region.
1430      * @exception NullPointerException (unchecked exception) Thrown if
1431      * <code>theSection</code> is null.
1432      * @exception IllegalStateException (unchecked exception) Thrown if no
1433      * parallel team is executing this parallel region.
1434      * @exception Exception Thrown if <code>theSection</code>'s <code>run()</code>
1435      * method throws an exception.
1436      * @throws java.lang.Exception if any.
1437      */
1438     public final void critical(ParallelSection theSection)
1439             throws Exception {
1440         critical(myLock, theSection);
1441     }
1442 
1443     /**
1444      * Perform a section of code in a critical region with nonexclusive locking.
1445      * The locking is performed using the default lock, a hidden {@linkplain
1446      * Lock} variable shared by all the parallel team threads. The thread
1447      * calling the <code>critical()</code> method waits until no other thread is
1448      * executing a critical region with exclusive locking using the default
1449      * lock. However, any number of other threads may be executing a critical
1450      * region with nonexclusive locking using the default lock. The thread then
1451      * calls <code>theSection</code>'s <code>run()</code> method with nonexclusive
1452      * locking using the default lock. When the <code>run()</code> method returns,
1453      * the thread unlocks the lock and returns from the <code>critical()</code>
1454      * method.
1455      * <P>
1456      * If the parallel section's <code>run()</code> method throws an exception, the
1457      * <code>critical()</code> method throws that same exception in the thread that
1458      * called the <code>run()</code> method (after unlocking the lock).
1459      *
1460      * @param theSection Parallel section to execute in the critical region.
1461      * @exception NullPointerException (unchecked exception) Thrown if
1462      * <code>theSection</code> is null.
1463      * @exception IllegalStateException (unchecked exception) Thrown if no
1464      * parallel team is executing this parallel region.
1465      * @exception Exception Thrown if <code>theSection</code>'s <code>run()</code>
1466      * method throws an exception.
1467      * @throws java.lang.Exception if any.
1468      */
1469     public final void criticalNonexclusive(ParallelSection theSection)
1470             throws Exception {
1471         criticalNonexclusive(myLock, theSection);
1472     }
1473 
1474     /**
1475      * Perform a section of code in a critical region with exclusive locking
1476      * using the given lock. The thread calling the <code>critical()</code> method
1477      * waits until no other thread is executing a critical region with exclusive
1478      * locking using the given lock and no other thread is executing a critical
1479      * region with nonexclusive locking using the given lock. The thread then
1480      * calls <code>theSection</code>'s <code>run()</code> method with exclusive locking
1481      * using the given lock. When the <code>run()</code> method returns, the thread
1482      * unlocks the lock and returns from the <code>critical()</code> method.
1483      * <P>
1484      * If the parallel section's <code>run()</code> method throws an exception, the
1485      * <code>critical()</code> method throws that same exception in the thread that
1486      * called the <code>run()</code> method (after unlocking the lock).
1487      *
1488      * @param theLock Lock.
1489      * @param theSection Parallel section to execute in the critical region.
1490      * @exception NullPointerException (unchecked exception) Thrown if
1491      * <code>theLock</code> is null or
1492      * <code>theSection</code> is null.
1493      * @exception IllegalStateException (unchecked exception) Thrown if no
1494      * parallel team is executing this parallel region.
1495      * @exception Exception Thrown if <code>theSection</code>'s <code>run()</code>
1496      * method throws an exception.
1497      * @throws java.lang.Exception if any.
1498      */
1499     public final void critical(Lock theLock,
1500             ParallelSection theSection)
1501             throws Exception {
1502         // Verify preconditions.
1503         if (theLock == null) {
1504             throw new NullPointerException("ParallelRegion.critical(): Lock is null");
1505         }
1506         if (theSection == null) {
1507             throw new NullPointerException("ParallelRegion.critical(): Parallel section is null");
1508         }
1509         if (myTeam == null) {
1510             throw new IllegalStateException("ParallelRegion.critical(): No parallel team executing");
1511         }
1512 
1513         // Lock the lock.
1514         theLock.lockExclusive();
1515 
1516         // Process the parallel section.
1517         try {
1518             theSection.myTeam = this.myTeam;
1519             theSection.run();
1520         } // Unlock the lock.
1521         finally {
1522             theSection.myTeam = null;
1523             theLock.unlockExclusive();
1524         }
1525     }
1526 
1527     /**
1528      * Perform a section of code in a critical region with nonexclusive locking
1529      * using the given lock. The thread calling the <code>critical()</code> method
1530      * waits until no other thread is executing a critical region with exclusive
1531      * locking using the given lock. However, any number of other threads may be
1532      * executing a critical region with nonexclusive locking using the given
1533      * lock. The thread then calls <code>theSection</code>'s <code>run()</code> method
1534      * with nonexclusive locking using the given lock. When the <code>run()</code>
1535      * method returns, the thread unlocks the lock and returns from the
1536      * <code>critical()</code> method.
1537      * <P>
1538      * If the parallel section's <code>run()</code> method throws an exception, the
1539      * <code>critical()</code> method throws that same exception in the thread that
1540      * called the <code>run()</code> method (after unlocking the lock).
1541      *
1542      * @param theLock Lock.
1543      * @param theSection Parallel section to execute in the critical region.
1544      * @exception NullPointerException (unchecked exception) Thrown if
1545      * <code>theLock</code> is null or
1546      * <code>theSection</code> is null.
1547      * @exception IllegalStateException (unchecked exception) Thrown if no
1548      * parallel team is executing this parallel region.
1549      * @exception Exception Thrown if <code>theSection</code>'s <code>run()</code>
1550      * method throws an exception.
1551      * @throws java.lang.Exception if any.
1552      */
1553     public final void criticalNonexclusive(Lock theLock,
1554             ParallelSection theSection)
1555             throws Exception {
1556         // Verify preconditions.
1557         if (theLock == null) {
1558             throw new NullPointerException("ParallelRegion.criticalNonexclusive(): Lock is null");
1559         }
1560         if (theSection == null) {
1561             throw new NullPointerException("ParallelRegion.criticalNonexclusive(): Parallel section is null");
1562         }
1563         if (myTeam == null) {
1564             throw new IllegalStateException("ParallelRegion.criticalNonexclusive(): No parallel team executing");
1565         }
1566 
1567         // Lock the lock.
1568         theLock.lockNonexclusive();
1569 
1570         // Process the parallel section.
1571         try {
1572             theSection.myTeam = this.myTeam;
1573             theSection.run();
1574         } // Unlock the lock.
1575         finally {
1576             theSection.myTeam = null;
1577             theLock.unlockNonexclusive();
1578         }
1579     }
1580 
1581     /**
1582      * Perform a barrier. The parallel team threads wait for each other at a
1583      * barrier.
1584      * <P>
1585      * <I>Note:</I> Either all threads in the parallel team must call the
1586      * <code>barrier()</code> method, or none of the threads must call the
1587      * <code>barrier()</code> method.
1588      *
1589      * @exception IllegalStateException (unchecked exception) Thrown if no
1590      * parallel team is executing this parallel region.
1591      */
1592     public final void barrier() {
1593         getCurrentThread().barrier();
1594     }
1595 
1596     /**
1597      * Perform a barrier, with a barrier action. The parallel team threads
1598      * encounter a barrier, and their behavior depends on the given {@linkplain
1599      * BarrierAction}.
1600      * <P>
1601      * <I>Note:</I> Either all threads in the parallel team must call the
1602      * <code>barrier()</code> method, or none of the threads must call the
1603      * <code>barrier()</code> method.
1604      *
1605      * @param action Barrier action.
1606      * @exception NullPointerException (unchecked exception) Thrown if
1607      * <code>action</code> is null.
1608      * @exception IllegalStateException (unchecked exception) Thrown if no
1609      * parallel team is executing this parallel region.
1610      * @exception Exception Thrown if <code>theSection</code>'s <code>run()</code>
1611      * method throws an exception.
1612      * @throws java.lang.Exception if any.
1613      */
1614     public final void barrier(BarrierAction action)
1615             throws Exception {
1616         if (action == null) {
1617             throw new NullPointerException("ParallelRegion.barrier(): Barrier action is null");
1618         }
1619         action.doBarrier(getCurrentThread());
1620     }
1621 
1622 }