| OLD | NEW |
| (Empty) |
| 1 /* The Computer Language Benchmarks Game | |
| 2 * http://benchmarksgame.alioth.debian.org/ | |
| 3 | |
| 4 contributed by Michael Barker | |
| 5 based on a Java contribution by Luzius Meisser | |
| 6 | |
| 7 convert to C by dualamd | |
| 8 */ | |
| 9 | |
| 10 #include <stdlib.h> | |
| 11 #include <stdio.h> | |
| 12 #include <pthread.h> | |
| 13 | |
| 14 | |
| 15 enum Colour | |
| 16 { | |
| 17 blue = 0, | |
| 18 red = 1, | |
| 19 yellow = 2, | |
| 20 Invalid = 3 | |
| 21 }; | |
| 22 | |
| 23 const char* ColourName[] = {"blue", "red", "yellow"}; | |
| 24 const int STACK_SIZE = 32*1024; | |
| 25 | |
| 26 typedef unsigned int BOOL; | |
| 27 const BOOL TRUE = 1; | |
| 28 const BOOL FALSE = 0; | |
| 29 | |
| 30 int CreatureID = 0; | |
| 31 | |
| 32 | |
| 33 enum Colour doCompliment(enum Colour c1, enum Colour c2) | |
| 34 { | |
| 35 switch (c1) | |
| 36 { | |
| 37 case blue: | |
| 38 switch (c2) | |
| 39 { | |
| 40 case blue: | |
| 41 return blue; | |
| 42 case red: | |
| 43 return yellow; | |
| 44 case yellow: | |
| 45 return red; | |
| 46 default: | |
| 47 goto errlb; | |
| 48 } | |
| 49 case red: | |
| 50 switch (c2) | |
| 51 { | |
| 52 case blue: | |
| 53 return yellow; | |
| 54 case red: | |
| 55 return red; | |
| 56 case yellow: | |
| 57 return blue; | |
| 58 default: | |
| 59 goto errlb; | |
| 60 } | |
| 61 case yellow: | |
| 62 switch (c2) | |
| 63 { | |
| 64 case blue: | |
| 65 return red; | |
| 66 case red: | |
| 67 return blue; | |
| 68 case yellow: | |
| 69 return yellow; | |
| 70 default: | |
| 71 goto errlb; | |
| 72 } | |
| 73 default: | |
| 74 break; | |
| 75 } | |
| 76 | |
| 77 errlb: | |
| 78 printf("Invalid colour\n"); | |
| 79 exit( 1 ); | |
| 80 } | |
| 81 | |
| 82 /* convert integer to number string: 1234 -> "one two three four" */ | |
| 83 char* formatNumber(int n, char* outbuf) | |
| 84 { | |
| 85 int ochar = 0, ichar = 0; | |
| 86 int i; | |
| 87 char tmp[64]; | |
| 88 | |
| 89 const char* NUMBERS[] = | |
| 90 { | |
| 91 "zero", "one", "two", "three", "four", "five", | |
| 92 "six", "seven", "eight", "nine" | |
| 93 }; | |
| 94 | |
| 95 ichar = sprintf(tmp, "%d", n); | |
| 96 | |
| 97 for (i = 0; i < ichar; i++) | |
| 98 ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] ); | |
| 99 | |
| 100 return outbuf; | |
| 101 } | |
| 102 | |
| 103 | |
| 104 struct MeetingPlace | |
| 105 { | |
| 106 pthread_mutex_t mutex; | |
| 107 int meetingsLeft; | |
| 108 struct Creature* firstCreature; | |
| 109 }; | |
| 110 | |
| 111 struct Creature | |
| 112 { | |
| 113 pthread_t ht; | |
| 114 pthread_attr_t stack_att; | |
| 115 | |
| 116 struct MeetingPlace* place; | |
| 117 int count; | |
| 118 int sameCount; | |
| 119 | |
| 120 enum Colour colour; | |
| 121 int id; | |
| 122 | |
| 123 BOOL two_met; | |
| 124 BOOL sameid; | |
| 125 }; | |
| 126 | |
| 127 | |
| 128 void MeetingPlace_Init(struct MeetingPlace* m, int meetings ) | |
| 129 { | |
| 130 pthread_mutex_init( &m->mutex, 0 ); | |
| 131 m->meetingsLeft = meetings; | |
| 132 m->firstCreature = 0; | |
| 133 } | |
| 134 | |
| 135 | |
| 136 BOOL Meet( struct Creature* cr) | |
| 137 { | |
| 138 BOOL retval = TRUE; | |
| 139 | |
| 140 struct MeetingPlace* mp = cr->place; | |
| 141 pthread_mutex_lock( &(mp->mutex) ); | |
| 142 | |
| 143 if ( mp->meetingsLeft > 0 ) | |
| 144 { | |
| 145 if ( mp->firstCreature == 0 ) | |
| 146 { | |
| 147 cr->two_met = FALSE; | |
| 148 mp->firstCreature = cr; | |
| 149 } | |
| 150 else | |
| 151 { | |
| 152 struct Creature* first; | |
| 153 enum Colour newColour; | |
| 154 | |
| 155 first = mp->firstCreature; | |
| 156 newColour = doCompliment( cr->colour, first->colour ); | |
| 157 | |
| 158 cr->sameid = cr->id == first->id; | |
| 159 cr->colour = newColour; | |
| 160 cr->two_met = TRUE; | |
| 161 | |
| 162 first->sameid = cr->sameid; | |
| 163 first->colour = newColour; | |
| 164 first->two_met = TRUE; | |
| 165 | |
| 166 mp->firstCreature = 0; | |
| 167 mp->meetingsLeft--; | |
| 168 } | |
| 169 } | |
| 170 else | |
| 171 retval = FALSE; | |
| 172 | |
| 173 pthread_mutex_unlock( &(mp->mutex) ); | |
| 174 return retval; | |
| 175 } | |
| 176 | |
| 177 | |
| 178 void* CreatureThreadRun(void* param) | |
| 179 { | |
| 180 struct Creature* cr = (struct Creature*)param; | |
| 181 | |
| 182 while (TRUE) | |
| 183 { | |
| 184 if ( Meet(cr) ) | |
| 185 { | |
| 186 while (cr->two_met == FALSE) | |
| 187 sched_yield(); | |
| 188 | |
| 189 if (cr->sameid) | |
| 190 cr->sameCount++; | |
| 191 cr->count++; | |
| 192 } | |
| 193 else | |
| 194 break; | |
| 195 } | |
| 196 | |
| 197 return 0; | |
| 198 } | |
| 199 | |
| 200 void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour
colour ) | |
| 201 { | |
| 202 cr->place = place; | |
| 203 cr->count = cr->sameCount = 0; | |
| 204 | |
| 205 cr->id = ++CreatureID; | |
| 206 cr->colour = colour; | |
| 207 cr->two_met = FALSE; | |
| 208 | |
| 209 pthread_attr_init( &cr->stack_att ); | |
| 210 pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE ); | |
| 211 pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) ); | |
| 212 } | |
| 213 | |
| 214 /* format meeting times of each creature to string */ | |
| 215 char* Creature_getResult(struct Creature* cr, char* str) | |
| 216 { | |
| 217 char numstr[256]; | |
| 218 formatNumber(cr->sameCount, numstr); | |
| 219 | |
| 220 sprintf( str, "%u%s", cr->count, numstr ); | |
| 221 return str; | |
| 222 } | |
| 223 | |
| 224 | |
| 225 void runGame( int n_meeting, int ncolor, const enum Colour* colours ) | |
| 226 { | |
| 227 int i; | |
| 228 int total = 0; | |
| 229 char str[256]; | |
| 230 | |
| 231 struct MeetingPlace place; | |
| 232 struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct
Creature) ); | |
| 233 | |
| 234 MeetingPlace_Init( &place, n_meeting ); | |
| 235 | |
| 236 /* print initial color of each creature */ | |
| 237 for (i = 0; i < ncolor; i++) | |
| 238 { | |
| 239 printf( "%s ", ColourName[ colours[i] ] ); | |
| 240 Creature_Init( &(creatures[i]), &place, colours[i] ); | |
| 241 } | |
| 242 printf("\n"); | |
| 243 | |
| 244 /* wait for them to meet */ | |
| 245 for (i = 0; i < ncolor; i++) | |
| 246 pthread_join( creatures[i].ht, 0 ); | |
| 247 | |
| 248 /* print meeting times of each creature */ | |
| 249 for (i = 0; i < ncolor; i++) | |
| 250 { | |
| 251 printf( "%s\n", Creature_getResult(&(creatures[i]), str) ); | |
| 252 total += creatures[i].count; | |
| 253 } | |
| 254 | |
| 255 /* print total meeting times, should equal n_meeting */ | |
| 256 printf( "%s\n\n", formatNumber(total, str) ); | |
| 257 | |
| 258 /* cleaup & quit */ | |
| 259 pthread_mutex_destroy( &place.mutex ); | |
| 260 free( creatures ); | |
| 261 } | |
| 262 | |
| 263 | |
| 264 void printColours( enum Colour c1, enum Colour c2 ) | |
| 265 { | |
| 266 printf( "%s + %s -> %s\n", | |
| 267 ColourName[c1], | |
| 268 ColourName[c2], | |
| 269 ColourName[doCompliment(c1, c2)] ); | |
| 270 } | |
| 271 | |
| 272 void printColoursTable(void) | |
| 273 { | |
| 274 printColours(blue, blue); | |
| 275 printColours(blue, red); | |
| 276 printColours(blue, yellow); | |
| 277 printColours(red, blue); | |
| 278 printColours(red, red); | |
| 279 printColours(red, yellow); | |
| 280 printColours(yellow, blue); | |
| 281 printColours(yellow, red); | |
| 282 printColours(yellow, yellow); | |
| 283 } | |
| 284 | |
| 285 int main(int argc, char** argv) | |
| 286 { | |
| 287 int n = (argc == 2) ? atoi(argv[1]) : 600; | |
| 288 | |
| 289 printColoursTable(); | |
| 290 printf("\n"); | |
| 291 | |
| 292 const enum Colour r1[] = { blue, red, yellow }; | |
| 293 const enum Colour r2[] = { blue, red, yellow, | |
| 294 red, yellow, blue, | |
| 295 red, yellow, red, blue }; | |
| 296 | |
| 297 runGame( n, sizeof(r1) / sizeof(r1[0]), r1 ); | |
| 298 runGame( n, sizeof(r2) / sizeof(r2[0]), r2 ); | |
| 299 | |
| 300 return 0; | |
| 301 } | |
| 302 | |
| OLD | NEW |