import tango.core.Thread;
import tango.util.locks.Barrier;
import tango.util.locks.Condition;
import tango.util.locks.Mutex;
import tango.util.locks.Semaphore;
import tango.text.convert.Integer;
import tango.io.Stdout;
typedef int Color;
const Color BLUE = 0, RED = 1, YELLOW = 2, FADED = 3;
void
main( char[][] args )
{
int remaining = ( 2 == args.length ? parse( args[ 1 ], 10 ) : 10 );
auto meetplaceSem = new Semaphore( 2 );
auto meetplaceLock = new Mutex;
auto meetCompleted = new Condition( meetplaceLock );
Color * swappedColor = null;
auto group = new ThreadGroup;
auto creatureStartBarrier = new Barrier( 2 );
int total = 0;
foreach( c; [ BLUE, RED, YELLOW, BLUE ] )
{
auto creature = new Thread(
{
auto my = c;
int creaturesMeet = 0;
creatureStartBarrier.wait;
Color processMeeting()
{
Color other = my;
meetplaceSem.acquire;
scope localLock = new ScopedLock( meetplaceLock );
if( !swappedColor )
{
if( remaining )
{
swappedColor = &other;
meetCompleted.wait();
swappedColor = null;
--remaining;
meetplaceSem.release;
}
else
other = FADED;
meetplaceSem.release;
}
else
{
other = *swappedColor;
*swappedColor = my;
meetCompleted.notify();
}
return other;
}
Color complement( Color other )
{
switch( my )
{
case BLUE: return other == RED ? YELLOW : RED;
case RED: return other == BLUE ? YELLOW : BLUE;
case YELLOW: return other == BLUE ? RED : BLUE;
default: break;
}
return my;
}
while( FADED != my )
{
Color other = processMeeting;
if( FADED != other )
{
my = complement( other );
++creaturesMeet;
}
else
my = FADED;
}
Stdout( "creaturesMeet: " )( creaturesMeet ).newline;
synchronized total += creaturesMeet;
} );
creature.start;
group.add( creature );
creatureStartBarrier.wait;
}
group.joinAll;
Stdout( total ).newline;
}
// vim:ts=2:sts=2:sw=2:expandtab:fenc=utf-8: