//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// datingService.c --
//
// Author           : Peter A. Buhr
// Created On       : Mon Oct 30 12:56:20 2017
// Last Modified By : Peter A. Buhr
// Last Modified On : Tue Jan  2 12:19:01 2018
// Update Count     : 22
//

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

enum { NoOfPairs = 20 };

monitor DatingService {
	condition Girls[NoOfPairs], Boys[NoOfPairs];
	unsigned int GirlPhoneNo, BoyPhoneNo;
}; // DatingService

unsigned int girl( DatingService & mutex ds, unsigned int PhoneNo, unsigned int ccode ) with( ds ) {
	if ( is_empty( Boys[ccode] ) ) {					// no compatible boy ?
		wait( Girls[ccode] );							// wait for boy
		GirlPhoneNo = PhoneNo;							// make phone number available
	} else {
		GirlPhoneNo = PhoneNo;							// make phone number available
		signal_block( Boys[ccode] );					// restart boy to set phone number
	} // if
	return BoyPhoneNo;
} // DatingService girl

unsigned int boy( DatingService & mutex ds, unsigned int PhoneNo, unsigned int ccode ) with( ds ) {
	if ( is_empty( Girls[ccode] ) ) {					// no compatible girl ?
		wait( Boys[ccode] );							// wait for girl
		BoyPhoneNo = PhoneNo;							// make phone number available
	} else {
		BoyPhoneNo = PhoneNo;							// make phone number available
		signal_block( Girls[ccode] );					// restart girl to set phone number
	} // if
	return GirlPhoneNo;
} // DatingService boy

unsigned int girlck[NoOfPairs];
unsigned int boyck[NoOfPairs];

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

void main( Girl & g ) with( g ) {
	yield( random( 100 ) );								// don't all start at the same time
	unsigned int partner = girl( TheExchange, id, ccode );
	sout | "Girl:" | id | "is dating Boy at" | partner | "with ccode" | ccode | endl;
	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 );
	sout | " Boy:" | id | "is dating Girl" | partner | "with ccode" | ccode | endl;
	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[NoOfPairs];
	Boy  *boys[NoOfPairs];

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

	for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
		girls[i] = new( &TheExchange, i, i );
		boys[i]  = new( &TheExchange, i, NoOfPairs - ( i + 1 ) );
	} // for

	for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
		delete( boys[i] );
		delete( girls[i] );
	} // for

	for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
		if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort();
	} // for
} // main

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