Index: src/tests/.expect/boundedBuffer.txt
===================================================================
--- src/tests/.expect/boundedBuffer.txt	(revision 1033f5dfc56a03ea95edeba1eba5aefef291dd4c)
+++ src/tests/.expect/boundedBuffer.txt	(revision 1033f5dfc56a03ea95edeba1eba5aefef291dd4c)
@@ -0,0 +1,1 @@
+total:500000
Index: src/tests/boundedBuffer.c
===================================================================
--- src/tests/boundedBuffer.c	(revision 1033f5dfc56a03ea95edeba1eba5aefef291dd4c)
+++ src/tests/boundedBuffer.c	(revision 1033f5dfc56a03ea95edeba1eba5aefef291dd4c)
@@ -0,0 +1,107 @@
+#include <stdlib>
+#include <fstream>
+#include <kernel>
+#include <thread>
+#include <unistd.h>					// getpid
+
+monitor Buffer {
+    condition full, empty;
+    int front, back, count;
+    int elements[20];
+};
+
+void ?{}( Buffer & buffer ) {
+    buffer.front = buffer.back = buffer.count = 0;
+}
+
+int query( Buffer & buffer ) { return buffer.count; }
+
+void insert( Buffer & mutex buffer, int elem ) {
+    if ( buffer.count == 20 ) wait( &buffer.empty );
+    buffer.elements[buffer.back] = elem;
+    buffer.back = ( buffer.back + 1 ) % 20;
+    buffer.count += 1;
+    signal( &buffer.full );
+}
+int remove( Buffer & mutex buffer ) {
+    if ( buffer.count == 0 ) wait( &buffer.full );
+    int elem = buffer.elements[buffer.front];
+    buffer.front = ( buffer.front + 1 ) % 20;
+    buffer.count -= 1;
+    signal( &buffer.empty );
+    return elem;
+}
+
+thread Producer {
+    Buffer * buffer;
+    unsigned int N;
+};
+void main( Producer & prod ) {
+    for ( int i = 1; i <= prod.N; i += 1 ) {
+	yield( (unsigned int)rand48() % 5 );
+	insert( *prod.buffer, 1 );
+    } // for
+    insert( *prod.buffer, -1 );
+}
+void ?{}( Producer & prod, Buffer * buffer, unsigned int N ) {
+    prod.buffer = buffer;
+    prod.N = N;
+}
+
+thread Consumer {
+    Buffer * buffer;
+    int * sum;						// summation of producer values
+};
+void main( Consumer & cons ) {
+    *cons.sum = 0;
+    for ( ;; ) {
+	yield( (unsigned int)rand48() % 5 );
+	int item = remove( *cons.buffer );
+      if ( item == -1 ) break;				// sentinel ?
+    	*cons.sum += item;
+    } // for
+}
+void ?{}( Consumer & cons, Buffer * buffer, int * sum ) {
+    cons.buffer = buffer;
+    cons.sum = sum;
+}
+
+forall(dtype T | sized(T) | { void ^?{}(T & mutex); })
+void delete( T * th ) {
+    ^(*th){};
+    free( th );
+}
+
+int main() {
+    Buffer buffer;
+    enum { Prods = 5, Cons = 5 };
+    Producer * prods[Prods];
+    Consumer * cons[Cons];
+    const int Sentinel = -1;
+    int sums[Cons];
+    int i;
+    processor p;
+
+    //rand48seed( getpid() );
+    rand48seed( 1003 );
+
+    for ( i = 0; i < Cons; i += 1 ) {			// create consumers
+	cons[i] = new( &buffer, &sums[i] );
+    } // for
+    for ( i = 0; i < Prods; i += 1 ) {			// create producers
+	prods[i] = new( &buffer, 100000u );
+    } // for
+
+    for ( i = 0; i < Prods; i += 1 ) {			// wait for producers to finish
+	delete( prods[i] );
+    } // for
+    for ( i = 0; i < Cons; i += 1 ) {			// generate sentinal values to stop consumers
+	insert( buffer, Sentinel );
+    } // for
+    int sum = 0;
+    for ( i = 0; i < Cons; i += 1 ) {			// wait for consumers to finish
+	delete( cons[i] );
+	sum += sums[i];
+    } // for
+    sout | "total:" | sum | endl;
+}
