Because kernel-threads are easier to understand C++CSP2 uses kernel-level threads by default (especially because of point 3 above) and because it fits the user's intuition that running parallel processes on a multi-core machine will take advantage of the multiple cores (see point 1 above).
The reason for providing user-threads at all is the last point on the list (point 4). Where performance or scalability is an issue, user-threads provide a way to improve performance over kernel-threading. So users who want to run simulations with tens or hundreds of thousands of processes will want to use a mixture of user-threads and kernel-threads, and will also want to read the section on stack sizes on the Processes page.
Wherever you see thread used on this page without a kernel- or user- qualifier, it means kernel-thread.
Both methods delete the process when the process has finished. Processes should always be allocated using the new operator, never on the stack. You should not delete processes yourself, and you should never attempt to run the same process twice (neither sequentially nor in parallel).
If not enough resources (either memory or OS resources) are available to create a thread, an OutOfResourcesException will be thrown. If you have made a call to spawn many processes, then the processes that have already started will stay running, but the processes that have not yet been run will be deleted. After the first failure, no further attempt is made to run any of the other processes.
If this error does occur, you will probably be left with half of your process network running, and half of it unstarted, which will probably cause your program to deadlock. You should probably attempt to poison all channels. This error is unlikely to occur unless you are running a very large program; common Windows and Linux machines should allow over a thousand processes (kernel-thread or user-thread) to be run in parallel without a problem.
Processes can be easily composed, either in parallel or in sequence. The following sections contain many examples of the use of the Run() function, and shows the result of each. All the processN variables are assumed to be of type CSProcess* unless specifically noted.
Run(process0);
RunInThisThread(process0);
Run( InParallel (process0) (process1) );
Run( InParallel(process0).with(process1) );
std::list<CSProcess*> processes; process0.push_back(process0); process1.push_back(process1); Run( InParallel( processes.begin() , processes.end() ) );
If you instead wanted to put process0 and process1 in the same new thread, you could do the following:
Run( InParallelOneThread(process0) (process1) );
If you instead want to put both process0 and process1 into the current thread, you could do the following:
RunInThisThread( InParallelOneThread(process0) (process1) );
Inquiring minds might wonder as to the effect of:
RunInThisThread( InParallel (process0) (process1) );
Run( InSequence (process0) (process1) );
Run( InSequence(process0).with(process1) );
std::list<CSProcess*> processes; process0.push_back(process0); process1.push_back(process1); Run( InSequence( processes.begin() , processes.end() ) );
Of course, process1 will not actually be started until process0 has finished - that is the point of composing processes in sequence. The threading arrangements that result from InSequence will be identical to InParallel (and InSequenceOneThread identical to InParallelOneThread), with this added restriction that each process will only be created when its immediate predecessor has finished.
Run( InParallel ( InSequence (process0) (process1) ) ( process2 ) ( InSequence ( process3 ) ( InParallel (process4) (process5) ) ) );
You may wish to compress this threading arrangement. For example, you may want to put process0 in the same thread as process1, and process 4 and process5 in the same thread as each other. This would be accomplished as follows:
Run( InParallel ( InSequenceOneThread (process0) (process1) ) ( process2 ) ( InSequence ( process3 ) ( InParallelOneThread (process4) (process5) ) ) );
Now consider if you wanted to put process0, process1 and process2 into one thread, and process3, process4 and process5 into another. That could be done as follows:
Run( InParallel ( InParallelOneThread ( InSequenceOneThread (process0) (process1) ) ( process2 ) ) ( InSequenceOneThread ( process3 ) ( InParallelOneThread (process4) (process5) ) ) );
For completeness, the effect of this:
Run( InParallel ( InParallelOneThread ( InSequence (process0) (process1) ) ( process2A ) ( process2B ) ) ( InSequenceOneThread ( process3A ) ( process3B ) ( InParallel (process4) (process5) ) ) );
All the four arrangements (InParallel, InSequence, InParallelOneThread, InSequenceOneThread ) are associative with themselves. That is, InParallel(x)(InParallel(y)(z)) produces the same threading arrangement as InParallel(x)(y)(InParallel(z)) and InParallel(x)(y)(z) (even taking into account the hidden helper processes). If you nest an InSequenceOneThread directly inside an InParallelOneThread (or vice versa) then the processes in both will be in the same thread.
In most cases, processes should be descended from CSProcess not ThreadCSProcess. But in case you use one that is descended from ThreadCSProcess, you should bear in mind that you cannot use them with one of the calls listed above. Similarly, you cannot nest an InParallel() or InSequence() directly inside an InParallelOneThread() or InSequenceOneThread(). You can however, achieve your desired effect by using the helper's process() call.
Classes | |
class | csp::ParallelHelper |
A helper class returned by the InParallel() function. More... | |
class | csp::ParallelHelperOneThread |
A helper class returned by the InParallelOneThread() function. More... | |
class | csp::RunHelper |
The base class for the various helper classes for the Run function. More... | |
class | csp::ScopedForking |
A class used to fork processes. More... | |
class | csp::SequentialHelper |
A helper class returned by the InSequence() function. More... | |
class | csp::SequentialHelperOneThread |
A helper class returned by the InSequenceOneThread() function. More... | |
Functions | |
template<typename ITERATOR> | |
ParallelHelper | csp::InParallel (ITERATOR begin, ITERATOR end) |
Starts an InParallel chain with the given processes. | |
ParallelHelper | csp::InParallel (const ParallelHelper &p) |
Starts an InParallel chain with the given helper. | |
ParallelHelper | csp::InParallel (ThreadCSProcessPtr p) |
Starts an InParallel chain with the given process. | |
template<typename ITERATOR> | |
ParallelHelperOneThread | csp::InParallelOneThread (ITERATOR begin, ITERATOR end) |
Starts an InParallelOneThread chain with the given processes. | |
ParallelHelperOneThread | csp::InParallelOneThread (CSProcessPtr p) |
Starts an InParallelOneThread chain with the given process. | |
template<typename ITERATOR> | |
SequentialHelper | csp::InSequence (ITERATOR begin, ITERATOR end) |
Starts an InSequence chain with the given processes. | |
SequentialHelper | csp::InSequence (ThreadCSProcessPtr p) |
Starts an InSequence chain with the given process. | |
template<typename ITERATOR> | |
SequentialHelperOneThread | csp::InSequenceOneThread (ITERATOR begin, ITERATOR end) |
Starts an InSequenceOneThread chain with the given processes. | |
SequentialHelperOneThread | csp::InSequenceOneThread (CSProcessPtr p) |
Starts an InSequenceOneThread chain with the given process. | |
void | csp::Run (ThreadCSProcessPtr) |
Runs the process in a new thread. | |
void | csp::Run (const SequentialHelperOneThread &) |
Runs the processes sequentially in one new thread. | |
void | csp::Run (const SequentialHelper &) |
Runs the processes sequentially in new threads. | |
void | csp::Run (const ParallelHelperOneThread &) |
Runs the parallel processes in one new thread. | |
void | csp::Run (const ParallelHelper &) |
Runs the parallel processes in new threads. | |
void | csp::RunInThisThread (const SequentialHelperOneThread &) |
Runs the processes sequentially in this thread. | |
void | csp::RunInThisThread (const ParallelHelperOneThread &) |
Runs the parallel processes in this thread. | |
void | csp::RunInThisThread (CSProcessPtr) |
Runs the process in this thread. |
void csp::Run | ( | const ParallelHelper & | ) |
Runs the parallel processes in new threads.
This function is usually called thus: Run(InParallel(x)(y)(z));
void csp::Run | ( | const ParallelHelperOneThread & | ) |
Runs the parallel processes in one new thread.
This function is usually called thus: Run(InParallelOneThread(x)(y)(z));
void csp::Run | ( | const SequentialHelper & | ) |
Runs the processes sequentially in new threads.
This function is usually called thus: Run(InSequence(x)(y)(z));
void csp::Run | ( | const SequentialHelperOneThread & | ) |
Runs the processes sequentially in one new thread.
This function is usually called thus: Run(InSequenceOneThread(x)(y)(z));
void csp::Run | ( | ThreadCSProcessPtr | ) |
Runs the process in a new thread.
void csp::RunInThisThread | ( | CSProcessPtr | ) |
Runs the process in this thread.
void csp::RunInThisThread | ( | const ParallelHelperOneThread & | ) |
Runs the parallel processes in this thread.
This function is usually called thus: RunInThisThread(InParallelOneThread(x)(y)(z));
void csp::RunInThisThread | ( | const SequentialHelperOneThread & | ) |
Runs the processes sequentially in this thread.
This function is usually called thus: RunInThisThread(InSequenceOneThread(x)(y)(z));
ParallelHelper csp::InParallel | ( | ThreadCSProcessPtr | p | ) | [inline] |
Starts an InParallel chain with the given process.
See the top of this page for information on how to use this function.
ParallelHelper csp::InParallel | ( | const ParallelHelper & | p | ) | [inline] |
Starts an InParallel chain with the given helper.
See the top of this page for information on how to use this function.
ParallelHelper csp::InParallel | ( | ITERATOR | begin, | |
ITERATOR | end | |||
) | [inline] |
Starts an InParallel chain with the given processes.
*ITERATOR is expected to resolve to a ThreadCSProcessPtr
ParallelHelperOneThread csp::InParallelOneThread | ( | CSProcessPtr | p | ) | [inline] |
Starts an InParallelOneThread chain with the given process.
See the top of this page for information on how to use this function.
ParallelHelperOneThread csp::InParallelOneThread | ( | ITERATOR | begin, | |
ITERATOR | end | |||
) | [inline] |
Starts an InParallelOneThread chain with the given processes.
*ITERATOR is expected to resolve to a CSProcessPtr
SequentialHelper csp::InSequence | ( | ThreadCSProcessPtr | p | ) | [inline] |
Starts an InSequence chain with the given process.
See the top of this page for information on how to use this function.
SequentialHelper csp::InSequence | ( | ITERATOR | begin, | |
ITERATOR | end | |||
) | [inline] |
Starts an InSequence chain with the given processes.
*ITERATOR is expected to resolve to a ThreadCSProcessPtr
SequentialHelperOneThread csp::InSequenceOneThread | ( | CSProcessPtr | p | ) | [inline] |
Starts an InSequenceOneThread chain with the given process.
See the top of this page for information on how to use this function.
SequentialHelperOneThread csp::InSequenceOneThread | ( | ITERATOR | begin, | |
ITERATOR | end | |||
) | [inline] |
Starts an InSequenceOneThread chain with the given processes.
*ITERATOR is expected to resolve to a CSProcessPtr