package shootout.chameneos; /* The Computer Language Benchmarks Game http://shootout.alioth.debian.org/ contributed by Michael Barker based on a contribution by Luzius Meisser */ /** * 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(). */ public class ChameneosRedux { enum Colour { blue, red, yellow } private static Colour doCompliment(Colour c1, Colour c2) { switch (c1) { case blue: switch (c2) { case blue: return Colour.blue; case red: return Colour.yellow; case yellow: return Colour.red; } case red: switch (c2) { case blue: return Colour.yellow; case red: return Colour.red; case yellow: return Colour.blue; } case yellow: switch (c2) { case blue: return Colour.red; case red: return Colour.blue; case yellow: return Colour.yellow; } } throw new RuntimeException("Error"); } static class MeetingPlace { private int meetingsLeft; public MeetingPlace(int meetings) { this.meetingsLeft = meetings; } private Colour firstColour = null; private int firstId = 0; Future<Pair> current; public Pair meet(int id, Colour c) throws Exception { Future<Pair> newPair; synchronized (this) { if (meetingsLeft == 0) { throw new Exception("Finished"); } else { if (firstColour == null) { firstColour = c; firstId = id; current = new Future<Pair>(); } else { Colour newColour = doCompliment(c, firstColour); current.setItem(new Pair(id == firstId, newColour)); firstColour = null; meetingsLeft--; } newPair = current; } } return newPair.getItem(); } } public static class Future<T> { private volatile T t; public T getItem() { while (t == null) { Thread.yield(); } return t; } // no synchronization necessary as assignment is atomic public void setItem(T t) { this.t = t; } } static class Creature implements Runnable { private final MeetingPlace place; private int count = 0; private int sameCount = 0; private Colour colour; private int id; public Creature(MeetingPlace place, Colour colour) { this.place = place; this.id = System.identityHashCode(this); this.colour = colour; } public void run() { try { while (true) { Pair p = place.meet(id, colour); colour = p.colour; if (p.sameId) { sameCount++; } count++; } } catch (Exception e) {} } public int getCount() { return count; } public String toString() { return String.valueOf(count) + getNumber(sameCount); } } private static void run(int n, boolean isWarm, Colour...colours) { MeetingPlace place = new MeetingPlace(n); Creature[] creatures = new Creature[colours.length]; for (int i = 0; i < colours.length; i++) { if (isWarm) System.out.print(" " + colours[i]); creatures[i] = new Creature(place, colours[i]); } if (isWarm) System.out.println(); Thread[] ts = new Thread[colours.length]; for (int i = 0; i < colours.length; i++) { ts[i] = new Thread(creatures[i]); ts[i].start(); } for (Thread t : ts) { try { t.join(); } catch (InterruptedException e) { } } int total = 0; for (Creature creature : creatures) { if (isWarm) System.out.println(creature); total += creature.getCount(); } if (isWarm) System.out.println(getNumber(total)); if (isWarm) System.out.println(); } public static void main(String[] args){ long start = System.currentTimeMillis(); for (int i=0; i<65; ++i) ChameneosRedux.program_main(args,false); ChameneosRedux.program_main(args,true); long total = System.currentTimeMillis() - start; System.out.println("[Chameneos Redux-Java Benchmark Result: " + total + "]"); } public static void program_main(String[] args, boolean isWarm) { int n = 600; try { n = Integer.parseInt(args[0]); } catch (Exception e) { } if (isWarm){ printColours(); System.out.println(); } run(n, isWarm, Colour.blue, Colour.red, Colour.yellow); run(n, isWarm, Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.yellow, Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.blue); } public static class Pair { public final boolean sameId; public final Colour colour; public Pair(boolean sameId, Colour c) { this.sameId = sameId; this.colour = c; } } private static final String[] NUMBERS = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; private static String getNumber(int n) { StringBuilder sb = new StringBuilder(); String nStr = String.valueOf(n); for (int i = 0; i < nStr.length(); i++) { sb.append(" "); sb.append(NUMBERS[Character.getNumericValue(nStr.charAt(i))]); } return sb.toString(); } private static 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); } private static void printColours(Colour c1, Colour c2) { System.out.println(c1 + " + " + c2 + " -> " + doCompliment(c1, c2)); } }