import tango.core.Thread;
import tango.core.Exception;
import tango.core.sync.Barrier;
import tango.core.sync.Condition;
import tango.core.sync.Mutex;
import tango.text.convert.Integer;
import tango.io.Stdout;
import tango.io.Console;
typedef int Color;
const Color BLUE = 0, RED = 1, YELLOW = 2, FADED = 3;
class MeetingPlace
{
this( int remaining )
{
remaining_ = remaining;
lock_ = new Mutex;
wakeup_ = new Condition( lock_ );
}
void meet( Creature me )
{
lock_.lock;
scope(exit) lock_.unlock;
if( remaining_ > 0 )
{
if( null is first_ )
{
first_ = &me;
wakeup_.wait();
}
else
{
me.other = first_.color;
first_.other = me.color;
first_ = null;
--remaining_;
wakeup_.notify();
}
}
else
{
me.other = FADED;
}
}
private :
int remaining_;
Creature * first_ = null;
Mutex lock_;
Condition wakeup_;
}
class Creature : Thread
{
this( Color selfColor, MeetingPlace meetingPlace )
{
super( &meeting );
color_ = selfColor;
meetingPlace_ = meetingPlace;
}
Color color() { return color_; }
Color other() { return other_; }
void other( Color value ) { other_ = value; }
int creaturesMeet() { return creaturesMeet_; }
private :
Color color_;
Color other_ = FADED;
MeetingPlace meetingPlace_ = null;
int creaturesMeet_ = 0;
void meeting()
{
while( color_ != FADED )
{
meetingPlace_.meet( this );
if( FADED != ( color_ = complement ) )
++creaturesMeet_;
}
}
Color complement()
{
if( FADED != other_ )
switch( color )
{
case BLUE: return other == RED ? YELLOW : RED;
case RED: return other == BLUE ? YELLOW : BLUE;
case YELLOW: return other == BLUE ? RED : BLUE;
default: break;
}
return FADED;
}
}
void
main( char[][] args )
{
int remaining = ( 2 == args.length ? parse( args[ 1 ], 10 ) : 10 );
auto meetingPlace = new MeetingPlace( remaining );
Creature[] creatures = [];
foreach( c; [ BLUE, RED, YELLOW, BLUE ] )
{
auto creature = new Creature( c, meetingPlace );
creatures ~= creature;
creature.start;
}
int total = 0;
foreach( c; creatures )
{
c.join;
total += c.creaturesMeet;
}
Stdout( total ).newline;
}
// vim:ts=2:sts=2:sw=2:expandtab:fenc=utf-8: