BACI Ben-Ari Concurrency Interpreter

BACI is a concurrency simulator. jBACI is an integration of the original BACI compilers and Strite’s interpreter into an IDE that contains an editor, together with extensions to the GUI to simplify its use by novices. jBACI is only available for Windows.

An installation guide can be found here:

http://www.bo-yang.net/2014/01/22/baci-simple-install-and-compile-guide/

BACI supports C– programming, which is a subset of C++ extended with primitives for process synchronization (semaphores and monitors). You can read the code reference written by Tracy Camp.

A lock free Producer/Consumer example is here:

// producer consumer 

binarysem output = 1;

int buffer[5];
int head, tail;

int max;

int push(int value) {
    if( head + 1 == tail ) { //full
        return -1;
    }
    buffer[head] = value;
    head++;
    if( head >= 5 ) {
        head = 0;
    }

    return 0;
}

int pop(int &value) {
    if( head == tail ) { //empty
        return -1;
    }
    value = buffer[tail];
    tail++;
    if( tail >= 5 ) {
        tail = 0;
    }

    return 0;
}

void producer() {
    int item = 1;
    while(item <= max) {
        while(push(item)) ; // push item until success
        wait(output);
        cout << "Item " << item << " produced" << endl;
        signal(output);
        item++;
    }
    wait(output);
    cout << "Producer exit" << endl;
    signal(output);
}

int mutex[2]; // maximum of 2 concurrent consumer

int lock(int id, int timeout) { //return -1 while timeout
    int time = 0;
    if( id == 1 ) {
        mutex[0] = 1;
        while(mutex[1]) {
            time++;
            if( time >= timeout ) {
                mutex[0] = 0;
                return -1;
            }
        }
    } else if ( id == 2 ) {
        mutex[1] = 1;
        while(mutex[0]) {
            time++;
            if( time >= timeout ) {
                mutex[1] = 0;
                return -1;;
            }
        }
    }

    return 0;
}

int free(int id) {
    if( mutex[ id - 1 ] == 0 ) {
        return -1;
    }
    mutex[ id - 1 ] = 0;
    return 0;
}

int finish = 0;

void consumer(int id) {
    int item = 0;
    while(item < max) {
        while(lock(id, 1024)) ;
        while(pop(item)) {
            if( finish ) {
                wait(output);
                cout << "Consumer C"<< id << " exit because job is finished" << endl;
                signal(output);
                return;
            }
        }
        wait(output);
        cout << "Item " << item << " consumed by C" << id << endl;
        signal(output);
        if( free(id) ) {
            wait(output);
            cout << "Consumer C"<< id << " free error" << endl;
            signal(output);
            return;
        }
    }

    wait(output);
    cout << "Consumer C"<< id << " exit" << endl;
    signal(output);
    finish = 1;
}

main()
{
    head = tail = 0;
    max = 100;
    mutex[0] = mutex[1] = 0;
    cobegin {
        producer();
        consumer(1);
        consumer(2);
    }
} // main

A lock free Reader/Writer example is here:

// reader/writer

binarysem output = 1;

int reader[3], writer[2]; // reader/writer flag

int mutex[2]; // maximum of 2 concurrent writer

int write_mutex(int id, int timeout) { //return -1 while timeout
    int time = 0;
    if( id = 1 ) {
        mutex[0] = 1;
        while(mutex[1]) {
            time++;
            if( time >= timeout ) {
                mutex[0] = 0;
                return -1;
            }
        }
    } else if ( id = 2 ) {
        mutex[1] = 1;
        while(mutex[0]) {
            time++;
            if( time >= timeout ) {
                mutex[1] = 0;
                return -1;;
            }
        }
    }

    return 0;
}

void writer_lock(int id) { // get the write permission
    int i;
    int timeout = 0;
    writer[ id - 1 ] = 1;
    for(i = 0; i < 3; i++) {
        timeout = 0;
        while(reader[i]) {
            if( timeout++ < 1024 ) {
                continue;
            }
            timeout = 0;
            writer[ id - 1 ] = 0; // turn off flag
            while( timeout++ < 1024 ) ;
            writer[ id - 1 ] = 1; // turn on flag again
            timeout = 0;
        }
    }
    while(write_mutex(id, 1024)) ; // 2 concurrent write
    wait(output);
    cout << "Writer " << id << " enters the critical section" << endl;
    signal(output);
}

void writer_free(int id) {
    writer[ id - 1 ] = 0;
    mutex[ id - 1 ] = 0;
    wait(output);
    cout << "Writer " << id << " leaves the critical section" << endl;
    signal(output);
}

void reader_lock(int id) { // read priority
    int timeout = 0;
    int i;
    reader[ id - 1 ] = 1;
    for(i = 0; i < 2; i++) {
        timeout = 0;
        while(writer[i]) {
            if( timeout++ < 1024 ) {
                continue;
            }
            timeout = 0;
            reader[ id - 1 ] = 0; // turn off flag
            while( timeout++ < 1024 ) ;
            reader[ id - 1 ] = 1; // turn on flag again
            timeout = 0;
        }
    }
    wait(output);
    cout << "Reader " << id << " enters the critical section" << endl;
    signal(output);
}

void reader_free(int id) {
    reader[ id - 1 ] = 0;
    wait(output);
    cout << "Reader " << id << " leaves the critical section" << endl;
    signal(output);
}

void read(int id)
{
    int i;
    for( i = 0; i < 4; i++) {
        reader_lock(id);
        reader_free(id);
    }
}

void write(int id)
{
    int i;
    for( i = 0; i < 3; i++) {
        writer_lock(id);
        writer_free(id);
    }
}

main()
{
    reader[0] = reader[1] = reader[2] = writer[0] = writer[1] = 0;
    mutex[0] = mutex[1];
    cobegin {
        write(1);
        write(2);
        read(1);
        read(2);
        read(3);
    }
} // main