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:

Hosted by uCoz