#include <stdlib.hfa>									// random
#include <fstream.hfa>
#include <kernel.hfa>
#include <thread.hfa>
#include <unistd.h>										// getpid

enum { CompCodes = 20 };								// number of compatibility codes

thread DatingService {
	condition Girls[CompCodes], Boys[CompCodes];
	unsigned int girlPhoneNo, boyPhoneNo, ccode;
}; // DatingService

unsigned int girl( DatingService & mutex ds, unsigned int phoneno, unsigned int code ) with( ds ) {
	girlPhoneNo = phoneno;  ccode = code;
	wait( Girls[ccode] );								// wait for boy
	girlPhoneNo = phoneno;
	sout | "Girl:" | girlPhoneNo | "is dating Boy at" | boyPhoneNo | "with ccode" | ccode;
	return boyPhoneNo;
} // DatingService girl

unsigned int boy( DatingService & mutex ds, unsigned int phoneno, unsigned int code ) with( ds ) {
	boyPhoneNo = phoneno;  ccode = code;
	wait( Boys[ccode] );								// wait for girl
	boyPhoneNo = phoneno;
	sout | " Boy:" | boyPhoneNo | "is dating Girl" | girlPhoneNo | "with ccode" | ccode;
	return girlPhoneNo;
} // DatingService boy

void main( DatingService & ds ) with( ds ) {			// thread starts
	for () {
		waitfor( ^?{} : ds ) {
			break;
		} or waitfor( girl : ds ) {
			if ( ! is_empty( Boys[ccode] ) ) {			// no compatible boy ?
				signal_block( Boys[ccode] );			// restart boy to set phone number
				signal_block( Girls[ccode] );			// restart girl to set phone number
			} // if
		} or waitfor( boy : ds ) {
			if ( ! is_empty( Girls[ccode] ) ) {			// no compatible girl ?
				signal_block( Girls[ccode] );			// restart girl to set phone number
				signal_block( Boys[ccode] );			// restart boy to set phone number
			} // if
		}
	}
} // DatingService main

unsigned int girlck[CompCodes];
unsigned int boyck[CompCodes];

thread Girl {
	DatingService & TheExchange;
	unsigned int id, ccode;
}; // Girl

void main( Girl & g ) with( g ) {
	yield( random( 100 ) );								// do not start at the same time
	unsigned int partner = girl( TheExchange, id, ccode );
	girlck[id] = partner;
} // Girl main

void ?{}( Girl & g, DatingService * TheExchange, unsigned int id, unsigned int ccode ) {
	&g.TheExchange = TheExchange;
	g.id = id;
	g.ccode = ccode;
} // Girl ?{}

thread Boy {
	DatingService & TheExchange;
	unsigned int id, ccode;
}; // Boy

void main( Boy & b ) with( b ) {
	yield( random( 100 ) );								// don't all start at the same time
	unsigned int partner = boy( TheExchange, id, ccode );
	boyck[id] = partner;
} // Boy main

void ?{}( Boy & b, DatingService * TheExchange, unsigned int id, unsigned int ccode ) {
	&b.TheExchange = TheExchange;
	b.id = id;
	b.ccode = ccode;
} // Boy ?{}

int main() {
	DatingService TheExchange;
	Girl * girls[CompCodes];
	Boy  * boys[CompCodes];

	srandom( /*getpid()*/ 103 );

	for ( i; (unsigned int)CompCodes ) {
		girls[i] = new( &TheExchange, i, i );			// TheExchange constructor needs unsigned int
		boys[i]  = new( &TheExchange, i, CompCodes - ( i + 1 ) );
	} // for

	for ( i; CompCodes ) {
		delete( boys[i] );
		delete( girls[i] );
	} // for

	for ( i; CompCodes ) {
		if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort();
	} // for
} // main

// Local Variables: //
// tab-width: 4 //
// compile-command: "cfa DatingServiceThread.cfa" //
// End: //
