/* The Computer Language Benchmarks Game http://shootout.alioth.debian.org/ contributed by Michael Barker based on a contribution by Luzius Meisser Convert to D by dualamd */ /** * This implementation uses standard Java threading (native threads). * * This implementation simply adds the new functionality to the orginal * implementation by Luzius Meisser from old chameneos shootout. The interesting * part of this implementation, is that while a creature is waiting it does not * block its thread, rather it spins in a loop using a Thread.yield(). */ import std.stdio; import std.thread : Thread; import std.c.linux.pthread; import std.conv; import std.string; enum Colour { blue, red, yellow, Invalid } const char[][3] ColourName = ["blue", "red", "yellow"]; int creatureID = 0; Colour doCompliment(Colour c1, Colour c2) { switch (c1) { case Colour.blue: switch (c2) { case Colour.blue: return Colour.blue; case Colour.red: return Colour.yellow; case Colour.yellow: return Colour.red; } case Colour.red: switch (c2) { case Colour.blue: return Colour.yellow; case Colour.red: return Colour.red; case Colour.yellow: return Colour.blue; } case Colour.yellow: switch (c2) { case Colour.blue: return Colour.red; case Colour.red: return Colour.blue; case Colour.yellow: return Colour.yellow; } } throw new Exception("Invalid colour"); } class Pair { public: bool two_met; bool sameId; Colour colour; void Meet(ref Pair p) { sameId = p.sameId; colour = p.colour; two_met = p.two_met; } void Meet(bool sameid, Colour c) { this.sameId = sameid; this.colour = c; two_met = true; } this() { two_met = false; } } class MeetingPlace { private: pthread_mutex_t mutex; int meetingsLeft; Colour firstColour = Colour.Invalid; int firstId = 0; Pair current; public: this(int meetings) { pthread_mutex_init( &mutex, null ); this.meetingsLeft = meetings; } ~this() { pthread_mutex_destroy( &mutex ); } bool meet(int id, Colour c, Pair rp) { pthread_mutex_lock( &mutex ); bool notfinish = true; if (meetingsLeft > 0) { if (firstColour == Colour.Invalid) { firstColour = c; firstId = id; rp.two_met = false; current = rp; } else { Colour newColour = doCompliment( c, firstColour ); rp.Meet( (id == firstId), newColour ); current.Meet( rp ); firstColour = Colour.Invalid; meetingsLeft--; } } else notfinish = false; pthread_mutex_unlock( &mutex ); return notfinish; } } class Creature : public Thread { private: MeetingPlace place; int count = 0; int sameCount = 0; Colour colour; int id; public: this(MeetingPlace place, Colour colour) { super(16*1024); //16KB stack for each thread this.place = place; this.id = ++creatureID; this.colour = colour; } override int run() { scope Pair p = new Pair(); while (true) { if ( place.meet(id, colour, p) ) { while (p.two_met == false) Thread.yield(); colour = p.colour; if (p.sameId) sameCount++; count++; } else break; } return 1; } int getCount() { return count; } string getResult() { string ret = std.string.toString(count); ret ~= getNumber(sameCount); return ret; } } void run(int n, Colour[] colours ...) { MeetingPlace place = new MeetingPlace(n); Creature[] creatures = new Creature[colours.length]; foreach (int i, cl; colours) { writef(ColourName[cl], " "); creatures[i] = new Creature(place, cl); } writefln(); foreach (c ; creatures) c.start(); foreach (t ; creatures) t.wait(); int total = 0; foreach (cr ; creatures) { writefln( cr.getResult() ); total += cr.getCount(); } writefln(getNumber(total)); writefln(); } char[] getNumber(int n) { const char[][10] NUMBERS = [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]; //char[] st = to!(char[])(n); string st = std.string.toString(n); char[] ret; foreach (c; st) { ret ~= " "; ret ~= NUMBERS[ c -'0' ]; } return ret; } void printColours(Colour c1, Colour c2) { writefln(ColourName[c1], " + ", ColourName[c2], " -> ", ColourName[doCompliment(c1, c2)]); } void printColours() { printColours(Colour.blue, Colour.blue); printColours(Colour.blue, Colour.red); printColours(Colour.blue, Colour.yellow); printColours(Colour.red, Colour.blue); printColours(Colour.red, Colour.red); printColours(Colour.red, Colour.yellow); printColours(Colour.yellow, Colour.blue); printColours(Colour.yellow, Colour.red); printColours(Colour.yellow, Colour.yellow); } void main(string[] args) { int n = 600; try { n = toInt(args[1]); } catch (Exception) {} printColours(); writefln(); run(n, Colour.blue, Colour.red, Colour.yellow); run(n, Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.yellow, Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.blue); }