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