golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/shootout/chameneosredux.c (about)

     1  // +build ignore
     2  
     3  /*
     4  Redistribution and use in source and binary forms, with or without
     5  modification, are permitted provided that the following conditions are met:
     6  
     7      * Redistributions of source code must retain the above copyright
     8      notice, this list of conditions and the following disclaimer.
     9  
    10      * Redistributions in binary form must reproduce the above copyright
    11      notice, this list of conditions and the following disclaimer in the
    12      documentation and/or other materials provided with the distribution.
    13  
    14      * Neither the name of "The Computer Language Benchmarks Game" nor the
    15      name of "The Computer Language Shootout Benchmarks" nor the names of
    16      its contributors may be used to endorse or promote products derived
    17      from this software without specific prior written permission.
    18  
    19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    20  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    21  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    22  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    23  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    24  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    25  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    26  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    27  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    28  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    29  POSSIBILITY OF SUCH DAMAGE.
    30  */
    31  
    32  /* The Computer Language Benchmarks Game
    33     http://shootout.alioth.debian.org/
    34  
    35     contributed by Michael Barker
    36     based on a Java contribution by Luzius Meisser
    37  
    38     convert to C by dualamd
    39  */
    40  
    41  #include <stdlib.h>
    42  #include <stdio.h>
    43  #include <pthread.h>
    44  
    45  
    46  enum Colour
    47  {
    48     blue      = 0,
    49     red      = 1,
    50     yellow   = 2,
    51     Invalid   = 3
    52  };
    53  
    54  const char* ColourName[] = {"blue", "red", "yellow"};
    55  const int STACK_SIZE   = 32*1024;
    56  
    57  typedef unsigned int BOOL;
    58  const BOOL TRUE = 1;
    59  const BOOL FALSE = 0;
    60  
    61  int CreatureID = 0;
    62  
    63  
    64  enum Colour doCompliment(enum Colour c1, enum Colour c2)
    65  {
    66     switch (c1)
    67     {
    68     case blue:
    69        switch (c2)
    70        {
    71        case blue:
    72           return blue;
    73        case red:
    74           return yellow;
    75        case yellow:
    76           return red;
    77        default:
    78           goto errlb;
    79        }
    80     case red:
    81        switch (c2)
    82        {
    83        case blue:
    84           return yellow;
    85        case red:
    86           return red;
    87        case yellow:
    88           return blue;
    89        default:
    90           goto errlb;
    91        }
    92     case yellow:
    93        switch (c2)
    94        {
    95        case blue:
    96           return red;
    97        case red:
    98           return blue;
    99        case yellow:
   100           return yellow;
   101        default:
   102           goto errlb;
   103        }
   104     default:
   105        break;
   106     }
   107  
   108  errlb:
   109     printf("Invalid colour\n");
   110     exit( 1 );
   111  }
   112  
   113  /* convert integer to number string: 1234 -> "one two three four" */
   114  char* formatNumber(int n, char* outbuf)
   115  {
   116     int ochar = 0, ichar = 0;
   117     int i;
   118     char tmp[64];
   119  
   120     const char* NUMBERS[] =
   121     {
   122        "zero", "one", "two", "three", "four", "five",
   123        "six", "seven", "eight", "nine"
   124     };
   125  
   126     ichar = sprintf(tmp, "%d", n);
   127  
   128     for (i = 0; i < ichar; i++)
   129        ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] );
   130  
   131     return outbuf;
   132  }
   133  
   134  
   135  struct MeetingPlace
   136  {
   137     pthread_mutex_t   mutex;
   138     int             meetingsLeft;
   139     struct Creature*   firstCreature;
   140  };
   141  
   142  struct Creature
   143  {
   144     pthread_t         ht;
   145     pthread_attr_t      stack_att;
   146  
   147     struct MeetingPlace* place;
   148     int         count;
   149     int         sameCount;
   150  
   151     enum Colour   colour;
   152     int          id;
   153  
   154     BOOL      two_met;
   155     BOOL      sameid;
   156  };
   157  
   158  
   159  void MeetingPlace_Init(struct MeetingPlace* m, int meetings )
   160  {
   161     pthread_mutex_init( &m->mutex, 0 );
   162     m->meetingsLeft = meetings;
   163     m->firstCreature = 0;
   164  }
   165  
   166  
   167  BOOL Meet( struct Creature* cr)
   168  {
   169     BOOL retval = TRUE;
   170  
   171     struct MeetingPlace* mp = cr->place;
   172     pthread_mutex_lock( &(mp->mutex) );
   173  
   174     if ( mp->meetingsLeft > 0 )
   175     {
   176        if ( mp->firstCreature == 0 )
   177        {
   178           cr->two_met = FALSE;
   179           mp->firstCreature = cr;
   180        }
   181        else
   182        {
   183           struct Creature* first;
   184           enum Colour newColour;
   185  
   186           first = mp->firstCreature;
   187           newColour = doCompliment( cr->colour, first->colour );
   188  
   189           cr->sameid = cr->id == first->id;
   190           cr->colour = newColour;
   191           cr->two_met = TRUE;
   192  
   193           first->sameid = cr->sameid;
   194           first->colour = newColour;
   195           first->two_met = TRUE;
   196  
   197           mp->firstCreature = 0;
   198           mp->meetingsLeft--;
   199        }
   200     }
   201     else
   202        retval = FALSE;
   203  
   204     pthread_mutex_unlock( &(mp->mutex) );
   205     return retval;
   206  }
   207  
   208  
   209  void* CreatureThreadRun(void* param)
   210  {
   211     struct Creature* cr = (struct Creature*)param;
   212  
   213     while (TRUE)
   214     {
   215        if ( Meet(cr) )
   216        {
   217           while (cr->two_met == FALSE)
   218              sched_yield();
   219  
   220           if (cr->sameid)
   221              cr->sameCount++;
   222           cr->count++;
   223        }
   224        else
   225           break;
   226     }
   227  
   228     return 0;
   229  }
   230  
   231  void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour )
   232  {
   233     cr->place = place;
   234     cr->count = cr->sameCount = 0;
   235  
   236     cr->id = ++CreatureID;
   237     cr->colour = colour;
   238     cr->two_met = FALSE;
   239  
   240     pthread_attr_init( &cr->stack_att );
   241     pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE );
   242     pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) );
   243  }
   244  
   245  /* format meeting times of each creature to string */
   246  char* Creature_getResult(struct Creature* cr, char* str)
   247  {
   248     char numstr[256];
   249     formatNumber(cr->sameCount, numstr);
   250  
   251     sprintf( str, "%u%s", cr->count, numstr );
   252     return str;
   253  }
   254  
   255  
   256  void runGame( int n_meeting, int ncolor, const enum Colour* colours )
   257  {
   258     int i;
   259     int total = 0;
   260     char str[256];
   261  
   262     struct MeetingPlace place;
   263     struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) );
   264  
   265     MeetingPlace_Init( &place, n_meeting );
   266  
   267     /* print initial color of each creature */
   268     for (i = 0; i < ncolor; i++)
   269     {
   270        printf( "%s ", ColourName[ colours[i] ] );
   271        Creature_Init( &(creatures[i]), &place, colours[i] );
   272     }
   273     printf("\n");
   274  
   275     /* wait for them to meet */
   276     for (i = 0; i < ncolor; i++)
   277        pthread_join( creatures[i].ht, 0 );
   278  
   279     /* print meeting times of each creature */
   280     for (i = 0; i < ncolor; i++)
   281     {
   282        printf( "%s\n", Creature_getResult(&(creatures[i]), str) );
   283        total += creatures[i].count;
   284     }
   285  
   286     /* print total meeting times, should equal n_meeting */
   287     printf( "%s\n\n", formatNumber(total, str) );
   288  
   289     /* cleaup & quit */
   290     pthread_mutex_destroy( &place.mutex );
   291     free( creatures );
   292  }
   293  
   294  
   295  void printColours( enum Colour c1, enum Colour c2 )
   296  {
   297     printf( "%s + %s -> %s\n",
   298        ColourName[c1],
   299        ColourName[c2],
   300        ColourName[doCompliment(c1, c2)]   );
   301  }
   302  
   303  void printColoursTable(void)
   304  {
   305     printColours(blue, blue);
   306     printColours(blue, red);
   307     printColours(blue, yellow);
   308     printColours(red, blue);
   309     printColours(red, red);
   310     printColours(red, yellow);
   311     printColours(yellow, blue);
   312     printColours(yellow, red);
   313     printColours(yellow, yellow);
   314  }
   315  
   316  int main(int argc, char** argv)
   317  {
   318     int n = (argc == 2) ? atoi(argv[1]) : 600;
   319  
   320     printColoursTable();
   321     printf("\n");
   322  
   323     const enum Colour r1[] = {   blue, red, yellow   };
   324     const enum Colour r2[] = {   blue, red, yellow,
   325                 red, yellow, blue,
   326                 red, yellow, red, blue   };
   327  
   328     runGame( n, sizeof(r1) / sizeof(r1[0]), r1 );
   329     runGame( n, sizeof(r2) / sizeof(r2[0]), r2 );
   330  
   331     return 0;
   332  }