//******************************************************************************
//
// File: ParallelRegion.java
// Package: edu.rit.pj
// Unit: Class edu.rit.pj.ParallelRegion
//
// This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************
package edu.rit.pj;
import edu.rit.util.LongRange;
import edu.rit.util.Range;
import java.util.Iterator;
/**
* Class ParallelRegion is the abstract base class for a parallel region that is
* executed by a {@linkplain ParallelTeam} of threads.
*
* To execute a parallel region, create a {@linkplain ParallelTeam} object;
* create an instance of a concrete subclass of class ParallelRegion; and pass
* this instance to the parallel team's execute() method. You can do
* all this using an anonymous inner class; for example:
*
* new ParallelTeam().execute (new ParallelRegion()
* {
* // Shared variable declarations
* . . .
* public void start()
* {
* // Initialization code
* . . .
* }
* public void run()
* {
* // Thread private variable declarations
* // Parallel code
* . . .
* }
* public void finish()
* {
* // Finalization code
* . . .
* }
* });
*
*
* The parallel team's execute() method does the following. The
* parallel team has a certain number of threads K, where K was
* specified when the parallel team was constructed. The main thread is the
* thread calling the parallel team's execute() method. The main thread
* calls the parallel region's start() method. When the
* start() method returns, all the team threads call the parallel
* region's run() method concurrently. When all the team threads have
* returned from the run() method, the main thread calls the parallel
* region's finish() method. When the finish() method returns,
* the main thread returns from the parallel team's execute() method.
*
* Variables to be shared by all threads in the team may be declared as fields
* of the ParallelRegion subclass. The start() method is intended for
* performing initialization in a single thread before parallel execution
* begins. If no such initialization is needed, omit the start()
* method. The run() method contains code to be executed in parallel by
* all threads in the team. Variables that are private to each thread may be
* declared inside the run() method. The finish() method is
* intended for performing finalization in a single thread after parallel
* execution ends. If no such finalization is needed, omit the finish()
* method.
*
* If the parallel region's start() method throws an exception, the
* parallel team's execute() method throws that same exception, and the
* run() method is not called.
*
* If the parallel region's run() method throws an exception in one of
* the team threads, the exception's stack trace is printed on the standard
* error, the parallel team waits until all the other team threads have returned
* from the run() method, then the parallel team's execute()
* method throws that same exception, and the parallel region's
* finish() method is not called. If the parallel region's
* run() method throws an exception in more than one of the team
* threads, each exception's stack trace is printed on the standard error, the
* parallel team waits until all the other team threads have returned from the
* run() method, then the parallel team's execute() method
* throws a {@linkplain MultipleParallelException} wrapping all the thrown
* exceptions, and the parallel region's finish() method is not called.
*
* If the parallel region's finish() method throws an exception, the
* parallel team's execute() method throws that same exception.
*
* @author Alan Kaminsky
* @version 11-Nov-2007
*/
public abstract class ParallelRegion
extends ParallelConstruct
{
// Hidden data members.
// Default lock for critical() and criticalNonexclusive() methods.
private Lock myLock = new Lock();
// Exported constructors.
/**
* Construct a new parallel region.
*/
public ParallelRegion()
{
super();
}
// Exported operations.
/**
* Perform initialization actions before parallel execution begins. Only one
* thread calls the start() method.
*
* The start() method may be overridden in a subclass. If not
* overridden, the start() method does nothing.
*
* @exception Exception
* The start() method may throw any exception.
*/
public void start()
throws Exception
{
}
/**
* Execute parallel code. All threads of the parallel team call the
* run() method concurrently.
*
* The run() method must be implemented in a subclass.
*
* @exception Exception
* The run() method may throw any exception.
*/
public abstract void run()
throws Exception;
/**
* Perform finalization actions after parallel execution ends. Only one
* thread calls the finish() method.
*
* The finish() method may be overridden in a subclass. If not
* overridden, the finish() method does nothing.
*
* @exception Exception
* The finish() method may throw any exception.
*/
public void finish()
throws Exception
{
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain IntegerForLoop}. The loop index goes
* from first (inclusive) to last (inclusive) in steps of
* +1. If first is greater than last, then no loop
* iterations are performed. At the end of the parallel for loop, the
* parallel team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param theLoop Parallel for loop.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(int first,
int last,
IntegerForLoop theLoop)
throws Exception
{
execute (first, last, theLoop, BarrierAction.WAIT);
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain IntegerForLoop}. The loop index goes
* from first (inclusive) to last (inclusive) in steps of
* +1. If first is greater than last, then no loop
* iterations are performed. At the end of the parallel for loop, the
* parallel team threads encounter a barrier, and their behavior depends on
* the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param theLoop Parallel for loop.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null. Thrown if
* action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(int first,
int last,
IntegerForLoop theLoop,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (theLoop == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel for loop is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theLoop.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
int currentIndex = currentThread.myIndex;
// Do top-of-parallel-construct processing.
IntegerSchedule schedule = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared parallel for loop
// schedule object and stores it (or an exception if any) in
// each team thread.
try
{
schedule = theLoop.schedule();
schedule.commonStart
(myTeam.K, new Range (first, last));
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setIntegerSchedule (schedule);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared parallel for loop schedule object.
schedule = currentThread.getIntegerSchedule();
theLoop.mySchedule = schedule;
// Prepare to catch exceptions thrown by the parallel for loop body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theLoop.start();
// Repeatedly get and process a chunk of loop iterations.
Range chunk;
while ((chunk = schedule.commonNext (currentIndex)) != null)
{
theLoop.commonRun (chunk.lb(), chunk.ub());
}
// Perform per-thread finalization.
theLoop.finish();
}
catch (Throwable exc)
{
runException = exc;
schedule.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theLoop.myTeam = null;
theLoop.mySchedule = null;
}
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain IntegerStrideForLoop}. The loop index
* goes from first (inclusive) to last (inclusive) in
* steps of stride. The stride must be positive. If first
* is greater than last, then no loop iterations are performed. At
* the end of the parallel for loop, the parallel team threads wait for each
* other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param stride Loop index stride, >= 1.
* @param theLoop Parallel for loop.
*
* @exception IllegalArgumentException
* (unchecked exception) Thrown if stride < 1.
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(int first,
int last,
int stride,
IntegerStrideForLoop theLoop)
throws Exception
{
execute (first, last, stride, theLoop, BarrierAction.WAIT);
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain IntegerStrideForLoop}. The loop index
* goes from first (inclusive) to last (inclusive) in
* steps of stride. The stride must be positive. If first
* is greater than last, then no loop iterations are performed. At
* the end of the parallel for loop, the parallel team threads encounter a
* barrier, and their behavior depends on the given {@linkplain
* BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param stride Loop index stride, >= 1.
* @param theLoop Parallel for loop.
* @param action Barrier action.
*
* @exception IllegalArgumentException
* (unchecked exception) Thrown if stride < 1.
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null. Thrown if
* action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(int first,
int last,
int stride,
IntegerStrideForLoop theLoop,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (stride <= 0)
{
throw new IllegalArgumentException
("ParallelRegion.execute(): Stride = " + stride + " illegal");
}
if (theLoop == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel for loop is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theLoop.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
int currentIndex = currentThread.myIndex;
// Do top-of-parallel-construct processing.
IntegerSchedule schedule = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared parallel for loop
// schedule object and stores it (or an exception if any) in
// each team thread.
try
{
schedule = theLoop.schedule();
schedule.commonStart
(myTeam.K, new Range (first, last, stride));
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setIntegerSchedule (schedule);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared parallel for loop schedule object.
schedule = currentThread.getIntegerSchedule();
theLoop.mySchedule = schedule;
// Prepare to catch exceptions thrown by the parallel for loop body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theLoop.start();
// Repeatedly get and process a chunk of loop iterations.
Range chunk;
while ((chunk = schedule.commonNext (currentIndex)) != null)
{
theLoop.commonRun (chunk.lb(), chunk.ub(), chunk.stride());
}
// Perform per-thread finalization.
theLoop.finish();
}
catch (Throwable exc)
{
runException = exc;
schedule.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theLoop.myTeam = null;
theLoop.mySchedule = null;
}
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain LongForLoop}. The loop index goes from
* first (inclusive) to last (inclusive) in steps of +1.
* If first is greater than last, then no loop iterations
* are performed. At the end of the parallel for loop, the parallel team
* threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param theLoop Parallel for loop.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(long first,
long last,
LongForLoop theLoop)
throws Exception
{
execute (first, last, theLoop, BarrierAction.WAIT);
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain LongForLoop}. The loop index goes from
* first (inclusive) to last (inclusive) in steps of +1.
* If first is greater than last, then no loop iterations
* are performed. At the end of the parallel for loop, the parallel team
* threads encounter a barrier, and their behavior depends on the given
* {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param theLoop Parallel for loop.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null. Thrown if
* action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(long first,
long last,
LongForLoop theLoop,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (theLoop == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel for loop is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theLoop.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
int currentIndex = currentThread.myIndex;
// Do top-of-parallel-construct processing.
LongSchedule schedule = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared parallel for loop
// schedule object and stores it (or an exception if any) in
// each team thread.
try
{
schedule = theLoop.schedule();
schedule.commonStart
(myTeam.K, new LongRange (first, last));
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setLongSchedule (schedule);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared parallel for loop schedule object.
schedule = currentThread.getLongSchedule();
theLoop.mySchedule = schedule;
// Prepare to catch exceptions thrown by the parallel for loop body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theLoop.start();
// Repeatedly get and process a chunk of loop iterations.
LongRange chunk;
while ((chunk = schedule.commonNext (currentIndex)) != null)
{
theLoop.commonRun (chunk.lb(), chunk.ub());
}
// Perform per-thread finalization.
theLoop.finish();
}
catch (Throwable exc)
{
runException = exc;
schedule.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theLoop.myTeam = null;
theLoop.mySchedule = null;
}
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain LongStrideForLoop}. The loop index
* goes from first (inclusive) to last (inclusive) in
* steps of stride. The stride must be positive. If first
* is greater than last, then no loop iterations are performed. At
* the end of the parallel for loop, the parallel team threads wait for each
* other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param stride Loop index stride, >= 1.
* @param theLoop Parallel for loop.
*
* @exception IllegalArgumentException
* (unchecked exception) Thrown if stride < 1.
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(long first,
long last,
long stride,
LongStrideForLoop theLoop)
throws Exception
{
execute (first, last, stride, theLoop, BarrierAction.WAIT);
}
/**
* Execute a parallel for loop within this parallel region. For further
* information, see class {@linkplain LongStrideForLoop}. The loop index
* goes from first (inclusive) to last (inclusive) in
* steps of stride. The stride must be positive. If first
* is greater than last, then no loop iterations are performed. At
* the end of the parallel for loop, the parallel team threads encounter a
* barrier, and their behavior depends on the given {@linkplain
* BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param first First loop index.
* @param last Last loop index.
* @param stride Loop index stride, >= 1.
* @param theLoop Parallel for loop.
* @param action Barrier action.
*
* @exception IllegalArgumentException
* (unchecked exception) Thrown if stride < 1.
* @exception NullPointerException
* (unchecked exception) Thrown if theLoop is null. Thrown if
* action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theLoop's methods throws an exception.
*/
public final void execute
(long first,
long last,
long stride,
LongStrideForLoop theLoop,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (stride <= 0)
{
throw new IllegalArgumentException
("ParallelRegion.execute(): Stride = " + stride + " illegal");
}
if (theLoop == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel for loop is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theLoop.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
int currentIndex = currentThread.myIndex;
// Do top-of-parallel-construct processing.
LongSchedule schedule = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared parallel for loop
// schedule object and stores it (or an exception if any) in
// each team thread.
try
{
schedule = theLoop.schedule();
schedule.commonStart
(myTeam.K, new LongRange (first, last, stride));
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setLongSchedule (schedule);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared parallel for loop schedule object.
schedule = currentThread.getLongSchedule();
theLoop.mySchedule = schedule;
// Prepare to catch exceptions thrown by the parallel for loop body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theLoop.start();
// Repeatedly get and process a chunk of loop iterations.
LongRange chunk;
while ((chunk = schedule.commonNext (currentIndex)) != null)
{
theLoop.commonRun (chunk.lb(), chunk.ub(), chunk.stride());
}
// Perform per-thread finalization.
theLoop.finish();
}
catch (Throwable exc)
{
runException = exc;
schedule.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theLoop.myTeam = null;
theLoop.mySchedule = null;
}
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the elements of the given array. The
* iteration order is from index 0 upwards. At the end of the parallel
* iteration, the parallel team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theArray Array containing the items.
* @param theIteration Parallel iteration.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null or
* theIteration is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(T[] theArray,
ParallelIteration theIteration)
throws Exception
{
execute (theArray, theIteration, BarrierAction.WAIT);
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the elements of the given array. The
* iteration order is from index 0 upwards. At the end of the parallel
* iteration, the parallel team threads encounter a barrier, and their
* behavior depends on the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theArray Array containing the items.
* @param theIteration Parallel iteration.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theArray is null. Thrown if
* theIteration is null. Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(T[] theArray,
ParallelIteration theIteration,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (theArray == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Array is null");
}
if (theIteration == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel iteration is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theIteration.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
// Do top-of-parallel-construct processing.
ItemGenerator generator = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared item generator
// object and stores it (or an exception if any) in each team
// thread.
try
{
generator = new ArrayItemGenerator (theArray);
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setItemGenerator (generator);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared item generator object.
generator = (ItemGenerator) currentThread.getItemGenerator();
theIteration.myItemGenerator = generator;
// Prepare to catch exceptions thrown by the parallel iteration
// body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theIteration.start();
// Repeatedly get and process an item.
ItemHolder itemholder;
while ((itemholder = generator.nextItem()) != null)
{
theIteration.commonRun
(itemholder.mySequenceNumber, itemholder.myItem);
}
// Perform per-thread finalization.
theIteration.finish();
}
catch (Throwable exc)
{
runException = exc;
generator.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theIteration.myTeam = null;
theIteration.myItemGenerator = null;
}
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the items returned by the given iterator.
* The iteration order is that of the given iterator. At the end of the
* parallel iteration, the parallel team threads wait for each other at a
* barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theIterator Iterator over the items.
* @param theIteration Parallel iteration.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theIterator is null or
* theIteration is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(Iterator theIterator,
ParallelIteration theIteration)
throws Exception
{
execute (theIterator, theIteration, BarrierAction.WAIT);
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the items returned by the given iterator.
* The iteration order is that of the given iterator. At the end of the
* parallel iteration, the parallel team threads encounter a barrier, and
* their behavior depends on the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theIterator Iterator over the items.
* @param theIteration Parallel iteration.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theIterator is null. Thrown
* if theIteration is null. Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(Iterator theIterator,
ParallelIteration theIteration,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (theIterator == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Iterator is null");
}
if (theIteration == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel iteration is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theIteration.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
// Do top-of-parallel-construct processing.
ItemGenerator generator = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared item generator
// object and stores it (or an exception if any) in each team
// thread.
try
{
generator = new IteratorItemGenerator (theIterator);
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setItemGenerator (generator);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared item generator object.
generator = (ItemGenerator) currentThread.getItemGenerator();
theIteration.myItemGenerator = generator;
// Prepare to catch exceptions thrown by the parallel iteration
// body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theIteration.start();
// Repeatedly get and process an item.
ItemHolder itemholder;
while ((itemholder = generator.nextItem()) != null)
{
theIteration.commonRun
(itemholder.mySequenceNumber, itemholder.myItem);
}
// Perform per-thread finalization.
theIteration.finish();
}
catch (Throwable exc)
{
runException = exc;
generator.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theIteration.myTeam = null;
theIteration.myItemGenerator = null;
}
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the items contained in the given iterable
* collection. The iteration order is that of the given iterable
* collection's iterator. At the end of the parallel iteration, the parallel
* team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theIterable Iterable collection containing the items.
* @param theIteration Parallel iteration.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theIterable is null or
* theIteration is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(Iterable theIterable,
ParallelIteration theIteration)
throws Exception
{
execute (theIterable, theIteration, BarrierAction.WAIT);
}
/**
* Execute a parallel iteration within this parallel region. For further
* information, see class {@linkplain ParallelIteration}. The items
* processed by the iteration are the items contained in the given iterable
* collection. The iteration order is that of the given iterable
* collection's iterator. At the end of the parallel iteration, the parallel
* team threads encounter a barrier, and their behavior depends on the given
* {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param Data type of the items iterated over.
* @param theIterable Iterable collection containing the items.
* @param theIteration Parallel iteration.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theIterable is null. Thrown
* if theIteration is null. Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of theIteration's methods throws an exception.
*/
public final void execute
(Iterable theIterable,
ParallelIteration theIteration,
BarrierAction action)
throws Exception
{
// Verify preconditions.
if (theIterable == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Iterable collection is null");
}
if (theIteration == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Parallel iteration is null");
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.execute(): No parallel team executing");
}
try
{
// Record parallel team.
theIteration.myTeam = this.myTeam;
// Get current parallel team thread.
ParallelTeamThread currentThread = getCurrentThread();
// Do top-of-parallel-construct processing.
ItemGenerator generator = null;
if (currentThread.arriveAtParallelConstruct())
{
// First thread to arrive sets up the shared item generator
// object and stores it (or an exception if any) in each team
// thread.
try
{
generator =
new IteratorItemGenerator (theIterable.iterator());
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setItemGenerator (generator);
}
}
catch (Throwable exc)
{
for (ParallelTeamThread thread : myTeam.myThread)
{
thread.setConstructException (exc);
}
}
}
// Get the shared item generator object.
generator = (ItemGenerator) currentThread.getItemGenerator();
theIteration.myItemGenerator = generator;
// Prepare to catch exceptions thrown by the parallel iteration
// body.
Throwable runException = null;
try
{
// Perform per-thread initialization.
theIteration.start();
// Repeatedly get and process an item.
ItemHolder itemholder;
while ((itemholder = generator.nextItem()) != null)
{
theIteration.commonRun
(itemholder.mySequenceNumber, itemholder.myItem);
}
// Perform per-thread finalization.
theIteration.finish();
}
catch (Throwable exc)
{
runException = exc;
generator.myBreak = true;
}
// Barrier synchronization.
action.doBarrier (currentThread);
// Propagate any exception thrown by the run() method.
ParallelTeam.rethrow (runException);
}
finally
{
// Forget parallel team.
theIteration.myTeam = null;
theIteration.myItemGenerator = null;
}
}
/**
* Execute a parallel section within this parallel region. The parallel
* section's run() method is called by one of the parallel team
* threads. For further information, see class {@linkplain ParallelSection}.
* At the end of the parallel section, the parallel team threads wait for
* each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section Parallel section.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if the parallel section's run() method throws an
* exception.
*/
public final void execute
(ParallelSection section)
throws Exception
{
execute (new ParallelSection[] {section}, BarrierAction.WAIT);
}
/**
* Execute a parallel section within this parallel region. The parallel
* section's run() method is called by one of the parallel team
* threads. For further information, see class {@linkplain ParallelSection}.
* At the end of the parallel section, the parallel team threads encounter a
* barrier, and their behavior depends on the given {@linkplain
* BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section Parallel section.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section is null. Thrown if
* action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if the parallel section's run() method throws an
* exception.
*/
public final void execute
(ParallelSection section,
BarrierAction action)
throws Exception
{
execute (new ParallelSection[] {section}, action);
}
/**
* Execute a group of two parallel sections concurrently within this
* parallel region. Each parallel section's run() method is called
* by a different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section1 First parallel section.
* @param section2 Second parallel section.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section1 is null. Thrown if
* section2 is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection section1,
ParallelSection section2)
throws Exception
{
execute
(new ParallelSection[] {section1, section2},
BarrierAction.WAIT);
}
/**
* Execute a group of two parallel sections concurrently within this
* parallel region. Each parallel section's run() method is called
* by a different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads encounter a barrier, and their behavior depends
* on the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section1 First parallel section.
* @param section2 Second parallel section.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section1 is null. Thrown if
* section2 is null. Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection section1,
ParallelSection section2,
BarrierAction action)
throws Exception
{
execute
(new ParallelSection[] {section1, section2},
action);
}
/**
* Execute a group of three parallel sections concurrently within this
* parallel region. Each parallel section's run() method is called
* by a different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section1 First parallel section.
* @param section2 Second parallel section.
* @param section3 Third parallel section.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section1 is null. Thrown if
* section2 is null. Thrown if section3 is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection section1,
ParallelSection section2,
ParallelSection section3)
throws Exception
{
execute
(new ParallelSection[] {section1, section2, section3},
BarrierAction.WAIT);
}
/**
* Execute a group of three parallel sections concurrently within this
* parallel region. Each parallel section's run() method is called
* by a different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads encounter a barrier, and their behavior depends
* on the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param section1 First parallel section.
* @param section2 Second parallel section.
* @param section3 Third parallel section.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if section1 is null. Thrown if
* section2 is null. Thrown if section3 is null.
* Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection section1,
ParallelSection section2,
ParallelSection section3,
BarrierAction action)
throws Exception
{
execute
(new ParallelSection[] {section1, section2, section3},
action);
}
/**
* Execute a group of parallel sections concurrently within this parallel
* region. Each parallel section's run() method is called by a
* different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads wait for each other at a barrier.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param sections Parallel sections.
*
* @exception NullPointerException
* (unchecked exception) Thrown if any of the sections is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection[] sections)
throws Exception
{
execute (sections, BarrierAction.WAIT);
}
/**
* Execute a group of parallel sections concurrently within this parallel
* region. Each parallel section's run() method is called by a
* different parallel team thread. For further information, see class
* {@linkplain ParallelSection}. At the end of the parallel section group,
* the parallel team threads encounter a barrier, and their behavior depends
* on the given {@linkplain BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* execute() method with identical arguments, or none of the
* threads must call the execute() method.
*
* @param sections Parallel sections.
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if any of the sections is null.
* Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if one of the parallel sections' run() methods throws
* an exception.
*/
public final void execute
(ParallelSection[] sections,
BarrierAction action)
throws Exception
{
if (sections == null)
{
throw new NullPointerException
("ParallelRegion.execute(): sections is null");
}
for (ParallelSection section : sections)
{
if (section == null)
{
throw new NullPointerException
("ParallelRegion.execute(): A parallel section is null");
}
}
if (action == null)
{
throw new NullPointerException
("ParallelRegion.execute(): Barrier action is null");
}
execute (sections, new ParallelIteration()
{
public void run (ParallelSection section) throws Exception
{
try
{
section.myTeam = this.myTeam;
section.run();
}
finally
{
section.myTeam = null;
}
}
},
action);
}
/**
* Perform a section of code in a critical region with exclusive locking.
* The locking is performed using the default lock, a hidden {@linkplain
* Lock} variable shared by all the parallel team threads. The thread
* calling the critical() method waits until no other thread is
* executing a critical region with exclusive locking using the default lock
* and no other thread is executing a critical region with nonexclusive
* locking using the default lock. The thread then calls
* theSection's run() method with exclusive locking using
* the default lock. When the run() method returns, the thread
* unlocks the lock and returns from the critical() method.
*
* If the parallel section's run() method throws an exception, the
* critical() method throws that same exception in the thread
* that called the run() method (after unlocking the lock).
*
* @param theSection Parallel section to execute in the critical region.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theSection is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if theSection's run() method throws an
* exception.
*/
public final void critical
(ParallelSection theSection)
throws Exception
{
critical (myLock, theSection);
}
/**
* Perform a section of code in a critical region with nonexclusive locking.
* The locking is performed using the default lock, a hidden {@linkplain
* Lock} variable shared by all the parallel team threads. The thread
* calling the critical() method waits until no other thread is
* executing a critical region with exclusive locking using the default
* lock. However, any number of other threads may be executing a critical
* region with nonexclusive locking using the default lock. The thread then
* calls theSection's run() method with nonexclusive
* locking using the default lock. When the run() method returns,
* the thread unlocks the lock and returns from the critical()
* method.
*
* If the parallel section's run() method throws an exception, the
* critical() method throws that same exception in the thread
* that called the run() method (after unlocking the lock).
*
* @param theSection Parallel section to execute in the critical region.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theSection is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if theSection's run() method throws an
* exception.
*/
public final void criticalNonexclusive
(ParallelSection theSection)
throws Exception
{
criticalNonexclusive (myLock, theSection);
}
/**
* Perform a section of code in a critical region with exclusive locking
* using the given lock. The thread calling the critical() method
* waits until no other thread is executing a critical region with exclusive
* locking using the given lock and no other thread is executing a critical
* region with nonexclusive locking using the given lock. The thread then
* calls theSection's run() method with exclusive locking
* using the given lock. When the run() method returns, the thread
* unlocks the lock and returns from the critical() method.
*
* If the parallel section's run() method throws an exception, the
* critical() method throws that same exception in the thread
* that called the run() method (after unlocking the lock).
*
* @param theLock Lock.
* @param theSection Parallel section to execute in the critical region.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLock is null or
* theSection is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if theSection's run() method throws an
* exception.
*/
public final void critical
(Lock theLock,
ParallelSection theSection)
throws Exception
{
// Verify preconditions.
if (theLock == null)
{
throw new NullPointerException
("ParallelRegion.critical(): Lock is null");
}
if (theSection == null)
{
throw new NullPointerException
("ParallelRegion.critical(): Parallel section is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.critical(): No parallel team executing");
}
// Lock the lock.
theLock.lockExclusive();
// Process the parallel section.
try
{
theSection.myTeam = this.myTeam;
theSection.run();
}
// Unlock the lock.
finally
{
theSection.myTeam = null;
theLock.unlockExclusive();
}
}
/**
* Perform a section of code in a critical region with nonexclusive locking
* using the given lock. The thread calling the critical() method
* waits until no other thread is executing a critical region with exclusive
* locking using the given lock. However, any number of other threads may be
* executing a critical region with nonexclusive locking using the given
* lock. The thread then calls theSection's run() method
* with nonexclusive locking using the given lock. When the run()
* method returns, the thread unlocks the lock and returns from the
* critical() method.
*
* If the parallel section's run() method throws an exception, the
* critical() method throws that same exception in the thread
* that called the run() method (after unlocking the lock).
*
* @param theLock Lock.
* @param theSection Parallel section to execute in the critical region.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theLock is null or
* theSection is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if theSection's run() method throws an
* exception.
*/
public final void criticalNonexclusive
(Lock theLock,
ParallelSection theSection)
throws Exception
{
// Verify preconditions.
if (theLock == null)
{
throw new NullPointerException
("ParallelRegion.criticalNonexclusive(): Lock is null");
}
if (theSection == null)
{
throw new NullPointerException
("ParallelRegion.criticalNonexclusive(): Parallel section is null");
}
if (myTeam == null)
{
throw new IllegalStateException
("ParallelRegion.criticalNonexclusive(): No parallel team executing");
}
// Lock the lock.
theLock.lockNonexclusive();
// Process the parallel section.
try
{
theSection.myTeam = this.myTeam;
theSection.run();
}
// Unlock the lock.
finally
{
theSection.myTeam = null;
theLock.unlockNonexclusive();
}
}
/**
* Perform a barrier. The parallel team threads wait for each other at a
* barrier.
*
* Note: Either all threads in the parallel team must call the
* barrier() method, or none of the threads must call the
* barrier() method.
*
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
*/
public final void barrier()
{
getCurrentThread().barrier();
}
/**
* Perform a barrier, with a barrier action. The parallel team threads
* encounter a barrier, and their behavior depends on the given {@linkplain
* BarrierAction}.
*
* Note: Either all threads in the parallel team must call the
* barrier() method, or none of the threads must call the
* barrier() method.
*
* @param action Barrier action.
*
* @exception NullPointerException
* (unchecked exception) Thrown if action is null.
* @exception IllegalStateException
* (unchecked exception) Thrown if no parallel team is executing this
* parallel region.
* @exception Exception
* Thrown if theSection's run() method throws an
* exception.
*/
public final void barrier
(BarrierAction action)
throws Exception
{
if (action == null)
{
throw new NullPointerException
("ParallelRegion.barrier(): Barrier action is null");
}
action.doBarrier (getCurrentThread());
}
}
Ads help maintain this website.