| 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 |