Metadata
Title
Thread Examples
Category
general
UUID
369da205bc254c22b6f6d6ef759dee14
Source URL
https://cforall.uwaterloo.ca/features/thread.shtml
Parent URL
https://cforall.uwaterloo.ca/features/
Crawl Time
2026-03-18T05:16:16+00:00
Rendered Raw Markdown

Thread Examples

Source: https://cforall.uwaterloo.ca/features/thread.shtml Parent: https://cforall.uwaterloo.ca/features/


Sum Matrix

Concurrently sum the rows of a matrix into subtotals and then sequential add the subtotals.

#include <fstream.hfa>
#include <thread.hfa>

thread Adder {
    int * row, cols, & subtotal;        // communication
};
void ?{}( Adder & adder, int row[], int cols, int & subtotal ) {
    adder.[row, cols] = [row, cols];    // expression disallowed in multi-member access
    &adder.subtotal = &subtotal;
}
void main( Adder & adder ) with( adder ) { // thread starts here
    subtotal = 0;
    for ( c; cols ) {
        subtotal += row[c];
    }
}
int main() {
    const int rows = 10, cols = 1000;
    int matrix[rows][cols], subtotals[rows], total = 0;
    processor p;                        // add kernel thread

    for ( r; rows ) {                   // initialize
        for ( c; cols ) {
            matrix[r][c] = 1;
        }
    }
    Adder * adders[rows];
    for ( r; rows ) {                   // start threads to sum rows
        adders[r] = &(*malloc()){ matrix[r], cols, subtotals[r] };
        // adders[r] = new( matrix[r], cols, subtotals[r] );
    }
    for ( r; rows ) {                   // wait for threads to finish
        delete( adders[r] );
        total += subtotals[r];          // total subtotals
    }
    sout | total;
}

Quick Sort

In-place concurrent quick-sort: threads are created to partition to a specific depth, then sequential recursive-calls are use to sort each partition.

thread Quicksort {
    int * values;                       // communication variables
    int low, high, depth;
};
void ?{}( Quicksort & qs, int values[], int size, int depth ) {
    qs.values = values;  qs.low = 0;  qs.high = size;  qs.depth = depth;
}
void main( Quicksort & qs ) {           // thread starts here
    // nested routines: information hiding
    void ?{}( Quicksort & qs, int values[], int low, int high, int depth ) {
        qs.values = values;  qs.low = low;  qs.high = high;  qs.depth = depth;
    }
    void sort( int values[], int low, int high, int depth ) {
        int left, right;                // index to left/right-hand side of the values
        int pivot;                      // pivot value of values
        int swap;                       // temporary
        // partition while 2 or more elements in the array
        if ( low < high ) {
            pivot = values[low + ( high - low ) / 2];
            left  = low;
            right = high;
            // partition: move values less < pivot before the pivot and values > pivot after the pivot
            do {
                while ( values[left] < pivot ) left += 1; // changed values[left] < pivot
                while ( pivot < values[right] ) right -= 1;
                if ( left <= right ) {
                    swap = values[left]; // interchange values
                    values[left]  = values[right];
                    values[right] = swap;
                    left += 1;
                    right -= 1;
                }
            } while ( left <= right );
            // restrict number of tasks to slightly greater than number of processors
            if ( depth > 0 ) {
                depth -= 1;
                Quicksort rqs = { values, low, right, depth }; // concurrently sort upper half
                sort( values, left, high, depth ); // concurrently sort lower half
            } else {
                sort( values, low, right, 0 ); // sequentially sort lower half
                sort( values, left, high, 0 ); // sequentially sort upper half
            }
        }
    }
    with( qs ) {
        sort( values, low, high, depth );
    }
}
int main() {
    // read size, depth, unsorted values
    processor processors[ (1 << depth) - 1 ]; // create 2^depth-1 kernel threads
    Quicksort QS = { values, size - 1, depth }; // sort values
}

Go Comparison

Comparison of Cāˆ€ waitfor and Go select. Call versus channel synchronization.

Cāˆ€ Go
#include <fstream.hfa> #include <thread.hfa> struct Msg { int i, j; }; thread Gortn { int i; float f; Msg m; }; void mem1( Gortn & mutex gortn, int i ) { gortn.i = i; } void mem2( Gortn & mutex gortn, float f ) { gortn.f = f; } void mem3( Gortn & mutex gortn, Msg m ) { gortn.m = m; } void ^?{}( Gortn & mutex ) {} void main( Gortn & gortn ) with( gortn ) { // thread starts for () { waitfor( mem1 : gortn ) sout | i; or waitfor( mem2 : gortn ) sout | f; or waitfor( mem3 : gortn ) sout | m.i | m.j; or waitfor( ^?{} : gortn ) break; } } int main() { Gortn gortn; // start thread mem1( gortn, 0 ); // different calls mem2( gortn, 2.5 ); mem3( gortn, (Msg){ 1, 2} ); } // wait for completion package main import "fmt" func main() { type Msg struct{ i, j int } ch1 := make( chan int ) ch2 := make( chan float32 ) ch3 := make( chan Msg ) hand := make( chan string ) shake := make( chan string ) gortn := func() { // thread starts var i int; var f float32; var m Msg L: for { select { // wait for message case i = <- ch1: fmt.Println( i ) case f = <- ch2: fmt.Println( f ) case m = <- ch3: fmt.Println( m ) case <- hand: break L // sentinel } } shake <- "SHAKE" // completion } go gortn() // start thread ch1 <- 0 // different messages ch2 <- 2.5 ch3 <- Msg{1, 2} hand <- "HAND" // sentinel value <-shake // wait for completion }