--- /dev/null
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of "The Computer Language Benchmarks Game" nor the
+ name of "The Computer Language Shootout Benchmarks" nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ http://shootout.alioth.debian.org/
+
+ contributed by Michael Barker
+ based on a Java contribution by Luzius Meisser
+
+ convert to C by dualamd
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+
+enum Colour
+{
+ blue = 0,
+ red = 1,
+ yellow = 2,
+ Invalid = 3
+};
+
+const char* ColourName[] = {"blue", "red", "yellow"};
+const int STACK_SIZE = 32*1024;
+
+typedef unsigned int BOOL;
+const BOOL TRUE = 1;
+const BOOL FALSE = 0;
+
+int CreatureID = 0;
+
+
+enum Colour doCompliment(enum Colour c1, enum Colour c2)
+{
+ switch (c1)
+ {
+ case blue:
+ switch (c2)
+ {
+ case blue:
+ return blue;
+ case red:
+ return yellow;
+ case yellow:
+ return red;
+ default:
+ goto errlb;
+ }
+ case red:
+ switch (c2)
+ {
+ case blue:
+ return yellow;
+ case red:
+ return red;
+ case yellow:
+ return blue;
+ default:
+ goto errlb;
+ }
+ case yellow:
+ switch (c2)
+ {
+ case blue:
+ return red;
+ case red:
+ return blue;
+ case yellow:
+ return yellow;
+ default:
+ goto errlb;
+ }
+ default:
+ break;
+ }
+
+errlb:
+ printf("Invalid colour\n");
+ exit( 1 );
+}
+
+/* convert integer to number string: 1234 -> "one two three four" */
+char* formatNumber(int n, char* outbuf)
+{
+ int ochar = 0, ichar = 0;
+ int i;
+ char tmp[64];
+
+ const char* NUMBERS[] =
+ {
+ "zero", "one", "two", "three", "four", "five",
+ "six", "seven", "eight", "nine"
+ };
+
+ ichar = sprintf(tmp, "%d", n);
+
+ for (i = 0; i < ichar; i++)
+ ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] );
+
+ return outbuf;
+}
+
+
+struct MeetingPlace
+{
+ pthread_mutex_t mutex;
+ int meetingsLeft;
+ struct Creature* firstCreature;
+};
+
+struct Creature
+{
+ pthread_t ht;
+ pthread_attr_t stack_att;
+
+ struct MeetingPlace* place;
+ int count;
+ int sameCount;
+
+ enum Colour colour;
+ int id;
+
+ BOOL two_met;
+ BOOL sameid;
+};
+
+
+void MeetingPlace_Init(struct MeetingPlace* m, int meetings )
+{
+ pthread_mutex_init( &m->mutex, 0 );
+ m->meetingsLeft = meetings;
+ m->firstCreature = 0;
+}
+
+
+BOOL Meet( struct Creature* cr)
+{
+ BOOL retval = TRUE;
+
+ struct MeetingPlace* mp = cr->place;
+ pthread_mutex_lock( &(mp->mutex) );
+
+ if ( mp->meetingsLeft > 0 )
+ {
+ if ( mp->firstCreature == 0 )
+ {
+ cr->two_met = FALSE;
+ mp->firstCreature = cr;
+ }
+ else
+ {
+ struct Creature* first;
+ enum Colour newColour;
+
+ first = mp->firstCreature;
+ newColour = doCompliment( cr->colour, first->colour );
+
+ cr->sameid = cr->id == first->id;
+ cr->colour = newColour;
+ cr->two_met = TRUE;
+
+ first->sameid = cr->sameid;
+ first->colour = newColour;
+ first->two_met = TRUE;
+
+ mp->firstCreature = 0;
+ mp->meetingsLeft--;
+ }
+ }
+ else
+ retval = FALSE;
+
+ pthread_mutex_unlock( &(mp->mutex) );
+ return retval;
+}
+
+
+void* CreatureThreadRun(void* param)
+{
+ struct Creature* cr = (struct Creature*)param;
+
+ while (TRUE)
+ {
+ if ( Meet(cr) )
+ {
+ while (cr->two_met == FALSE)
+ sched_yield();
+
+ if (cr->sameid)
+ cr->sameCount++;
+ cr->count++;
+ }
+ else
+ break;
+ }
+
+ return 0;
+}
+
+void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour )
+{
+ cr->place = place;
+ cr->count = cr->sameCount = 0;
+
+ cr->id = ++CreatureID;
+ cr->colour = colour;
+ cr->two_met = FALSE;
+
+ pthread_attr_init( &cr->stack_att );
+ pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE );
+ pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) );
+}
+
+/* format meeting times of each creature to string */
+char* Creature_getResult(struct Creature* cr, char* str)
+{
+ char numstr[256];
+ formatNumber(cr->sameCount, numstr);
+
+ sprintf( str, "%u%s", cr->count, numstr );
+ return str;
+}
+
+
+void runGame( int n_meeting, int ncolor, const enum Colour* colours )
+{
+ int i;
+ int total = 0;
+ char str[256];
+
+ struct MeetingPlace place;
+ struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) );
+
+ MeetingPlace_Init( &place, n_meeting );
+
+ /* print initial color of each creature */
+ for (i = 0; i < ncolor; i++)
+ {
+ printf( "%s ", ColourName[ colours[i] ] );
+ Creature_Init( &(creatures[i]), &place, colours[i] );
+ }
+ printf("\n");
+
+ /* wait for them to meet */
+ for (i = 0; i < ncolor; i++)
+ pthread_join( creatures[i].ht, 0 );
+
+ /* print meeting times of each creature */
+ for (i = 0; i < ncolor; i++)
+ {
+ printf( "%s\n", Creature_getResult(&(creatures[i]), str) );
+ total += creatures[i].count;
+ }
+
+ /* print total meeting times, should equal n_meeting */
+ printf( "%s\n\n", formatNumber(total, str) );
+
+ /* cleaup & quit */
+ pthread_mutex_destroy( &place.mutex );
+ free( creatures );
+}
+
+
+void printColours( enum Colour c1, enum Colour c2 )
+{
+ printf( "%s + %s -> %s\n",
+ ColourName[c1],
+ ColourName[c2],
+ ColourName[doCompliment(c1, c2)] );
+}
+
+void printColoursTable(void)
+{
+ printColours(blue, blue);
+ printColours(blue, red);
+ printColours(blue, yellow);
+ printColours(red, blue);
+ printColours(red, red);
+ printColours(red, yellow);
+ printColours(yellow, blue);
+ printColours(yellow, red);
+ printColours(yellow, yellow);
+}
+
+int main(int argc, char** argv)
+{
+ int n = (argc == 2) ? atoi(argv[1]) : 600;
+
+ printColoursTable();
+ printf("\n");
+
+ const enum Colour r1[] = { blue, red, yellow };
+ const enum Colour r2[] = { blue, red, yellow,
+ red, yellow, blue,
+ red, yellow, red, blue };
+
+ runGame( n, sizeof(r1) / sizeof(r1[0]), r1 );
+ runGame( n, sizeof(r2) / sizeof(r2[0]), r2 );
+
+ return 0;
+}
--- /dev/null
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of "The Computer Language Benchmarks Game" nor the
+ name of "The Computer Language Shootout Benchmarks" nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ */
+
+package main
+
+import (
+ "flag";
+ "fmt";
+ "os";
+)
+
+var n = flag.Int("n", 600, "count")
+
+type Color int
+
+const (
+ blue Color = iota;
+ red;
+ yellow;
+)
+
+func (c Color) String() string {
+ return []string{"blue", "red", "yellow"}[c]
+}
+
+func complement(c1, c2 Color) Color {
+ switch c1 << 2 | c2 {
+ case blue << 2 | blue:
+ return blue
+ case blue << 2 | red:
+ return yellow
+ case blue << 2 | yellow:
+ return red
+ case red << 2 | blue:
+ return yellow
+ case red << 2 | red:
+ return red
+ case red << 2 | yellow:
+ return blue
+ case yellow << 2 | blue:
+ return red
+ case yellow << 2 | red:
+ return blue
+ case yellow << 2 | yellow:
+ return yellow
+ }
+ fmt.Println("invalid colors", c1, c2);
+ os.Exit(2);
+ return 0
+}
+
+func printColors(c1, c2 Color) {
+ fmt.Printf("%s + %s -> %s\n", c1, c2, complement(c1, c2));
+}
+
+func printColorTable() {
+ printColors(blue, blue);
+ printColors(blue, red);
+ printColors(blue, yellow);
+ printColors(red, blue);
+ printColors(red, red);
+ printColors(red, yellow);
+ printColors(yellow, blue);
+ printColors(yellow, red);
+ printColors(yellow, yellow);
+}
+
+type Referee struct {
+ rendezCount int;
+ cham []*Chameneos;
+ rendez chan *Chameneos;
+ done chan int;
+}
+
+func NewReferee() *Referee {
+ ref := new(Referee);
+ ref.cham = make([]*Chameneos, 0, 100);
+ ref.rendez = make(chan *Chameneos);
+ ref.done = make(chan int);
+ go ref.Serve();
+ return ref;
+}
+
+func (ref *Referee) Serve() {
+ for i := 0; i < *n; i++ {
+ c1 := <-ref.rendez;
+ c2 := <-ref.rendez;
+ c1.col, c2.col = complement(c1.col, c2.col), complement(c2.col, c1.col);
+ c1.rendez <- c2;
+ c2.rendez <- c1;
+ }
+ for i := 0; i < len(ref.cham); i++ {
+ c := <-ref.rendez;
+ c.rendez <- nil;
+ }
+ ref.done <- 1;
+}
+
+func (ref *Referee) Add(ch *Chameneos) {
+ n := len(ref.cham);
+ ref.cham = ref.cham[0:n+1];
+ ref.cham[n] = ch;
+}
+
+type Chameneos struct {
+ index int;
+ col Color;
+ rendez chan *Chameneos;
+ count int;
+ same int;
+ ref *Referee;
+}
+
+func (c *Chameneos) Init(index int, ref *Referee, col Color) *Chameneos {
+ c.index = index;
+ c.ref = ref;
+ c.col = col;
+ c.rendez = make(chan *Chameneos);
+ go c.Serve();
+ return c;
+}
+
+func (c *Chameneos) Serve() {
+ for {
+ c.ref.rendez <- c;
+ c1 := <- c.rendez;
+ if c1 == nil {
+ break
+ }
+ if c1.index == c.index {
+ c.same++
+ }
+ c.count++;
+ }
+}
+
+func play(ref *Referee, color []Color) {
+ cham := make([]Chameneos, len(color));
+ for i, c := range color {
+ fmt.Printf("%s ", c);
+ ref.Add(cham[i].Init(i, ref, c));
+ }
+ fmt.Printf("\n");
+ <-ref.done;
+ total := 0;
+ for i, c := range cham {
+ total += c.count;
+ fmt.Printf("%d %s\n", c.count, say(c.same));
+ }
+ fmt.Printf("%s\n\n", say(total));
+}
+
+var words = []string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
+
+func say(n int) string {
+ digits := fmt.Sprint(n);
+ s := "";
+ for _, c := range digits {
+ s += " " + words[c-'0'];
+ }
+ return s;
+}
+
+func main() {
+ flag.Parse();
+ printColorTable();
+ fmt.Print("\n");
+ play(NewReferee(), []Color{blue, red, yellow});
+ play(NewReferee(), []Color{blue, red, yellow, red, yellow, blue, red, yellow, red, blue});
+}