import tango.core.Thread; import tango.util.locks.Condition; import tango.util.locks.Mutex; import tango.text.convert.Integer; import tango.io.Stdout; typedef int Color; const Color BLUE = 0; const Color RED = 1; const Color YELLOW = 2; const Color FADED = 3; class MeetingPlace { int remaining_ = 10; Mutex lock_; Condition meetplaceAvailable_; Condition meetCompleted_; int creaturesInside_ = 0; Color * swappedColor_ = null; this() { lock_ = new Mutex; meetplaceAvailable_ = new Condition( lock_ ); meetCompleted_ = new Condition( lock_ ); } } class Creature : Thread { this( Color my, MeetingPlace meetingPlace ) { super( &run ); my_ = my; meetingPlace_ = meetingPlace; } void run() { while( true ) { Color other = processMeeting; if( FADED != other ) { my_ = complement( other ); ++creaturesMeet_; } else { my_ = FADED; break; } } } int total() { return creaturesMeet_; } private : Color my_; MeetingPlace meetingPlace_; int creaturesMeet_ = 0; Color processMeeting() { Color other = my_; with( meetingPlace_ ) { scope localLock = new ScopedLock( lock_ ); // We must wait for meetplace if some pair is already inside. while( creaturesInside_ == 2 ) meetplaceAvailable_.wait(); if( remaining_ ) { if( !swappedColor_ ) { creaturesInside_ = 1; swappedColor_ = &other; // Wait for second creature to make pair. meetCompleted_.wait(); // Clean stuff after the meeting. swappedColor_ = null; creaturesInside_ = 0; --remaining_; // All awaiting outside creatures may come in. meetplaceAvailable_.notifyAll; } else { // The pair inside. creaturesInside_ = 2; // Color exchange. other = *swappedColor_; *swappedColor_ = my_; // The first creature may wake up. meetCompleted_.notify(); } } else other = FADED; } 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_; } } void main( char[][] args ) { auto meetingPlace = new MeetingPlace; if( 2 == args.length ) meetingPlace.remaining_ = parse( args[ 1 ], 10 ); auto colors = [ BLUE, RED, YELLOW, BLUE ]; Creature[] group; foreach( color; colors ) { Creature creature = new Creature( color, meetingPlace ); group ~= creature; creature.start; } int total = 0; foreach( c; group ) { c.join; total += c.total; } Stdout( total ).newline; } // vim:ts=2:sts=2:sw=2:expandtab:fenc=utf-8: