Concurrency

COBEGIN / COEND

COBEGIN/COEND is a compound statement that runs each of its inner BEGIN ... END blocks on a separate thread. The initial thread waits at COEND for every internal thread to finish — a built-in fork/join barrier.

Why this shape rather than free-form thread spawning?

It guarantees structured concurrency: threads created together finish together, so there’s no way to “leak” a thread past its enclosing block. The downside is expressiveness — the fork/join pattern makes it restricted to trees (lattices) of threads, not arbitrary thread graphs. Arbitrary graphs need WAIT.

uC++ form

#include <uCobegin.h>
int i;
void p1( ... );  void p2( ... );  void p3( ... );
COBEGIN                         // threads execute statements in block
    BEGIN i = 1;     END
    BEGIN p1( 5 );   END        // order and speed of internal
    BEGIN p2( 7 );   END        // thread execution is unknown
    BEGIN p3( 9 );   END
COEND                           // initial thread waits for all internals

Dynamic thread count via recursion

void loop( int N ) {
    if ( N != 0 ) {
        COBEGIN
            BEGIN p1( ... );    END
            BEGIN loop( N - 1 ); END  // recursive call
        COEND
    }
}
cin >> N;
loop( N );

Limitation — trees only

The thread graph implied by nested COBEGIN/COEND is strictly a tree. You can’t express “p starts before f, both finish before s4” without creating artificial nesting. For arbitrary graphs, use WAIT.