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 meetplaceLock = new Mutex; auto meetCompleted = new Condition( meetplaceLock ); auto meetplaceAvailable = new Condition( meetplaceLock ); int creaturesInside = 0; 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; scope localLock = new ScopedLock( meetplaceLock ); 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; } 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: