--- trunk/livstidsfanger.c 2014/11/07 07:51:12 3 +++ trunk/livstidsfanger.c 2014/11/08 11:56:59 11 @@ -1,20 +1,22 @@ // Programmet bruker ISO C 2011 (ISO/IEC 9899:2011) og Pthreads (IEEE Std 1003.1c-1995). -*- coding: utf-8 -*- -// Løsning laget av Trond Endrestøl , 2014-11-06. +// Løsning programmert av Trond Endrestøl , 2014-11-06. // $Ximalas$ #include #include #include +#include #include #include #include +#include #include #if __STDC_VERSION__ >= 201112L #include #else -#define noreturn /**/ +#define noreturn #endif #define ANTALL_LIVSTIDSFANGER 19U @@ -26,23 +28,25 @@ static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static bool brytere[2U]; -// Ingen må forandre på bryterne uten å ha låst mutex først. -static unsigned brytere[2U]; - noreturn void *livstidsfange(void *arg); void visResultater(void); void signalhandler(int sig); -noreturn int main (int argc, char **argv) +noreturn int main(int argc, char **argv) { size_t i; - pthread_t tid = 0; + pthread_t tid = pthread_self(); atexit(visResultater); signal(SIGINT, signalhandler); +#ifdef __FreeBSD__ srandomdev(); +#else + srandom((unsigned int)time(NULL)); +#endif memset((void *)&antallBesok, 0, sizeof(antallBesok)); brytere[0] = random() & 1; @@ -50,6 +54,10 @@ noreturn int main (int argc, char **argv) tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER; + printf("bryter %u er i utgangspunktet vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned"); + printf("bryter %u er i utgangspunktet vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned"); + printf("livstidsfange %zu er utpekt som den tellende livstidsfange\n\n", tellendeLivstidsfange + 1); + puts("maintråden venter på å få låst mutex"); pthread_mutex_lock(&mutex); puts("mutex er låst av maintråden"); @@ -57,11 +65,13 @@ noreturn int main (int argc, char **argv) for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) { printf("maintråden oppretter livstidsfange %2zu\n", i + 1); - if ( ( errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) { + if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) { + fflush(stdout); fprintf(stderr, "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n", argv[0], i, strerror(errno), errno); - exit(1); + fflush(stderr); + _exit(1); } // if } // for @@ -85,11 +95,11 @@ noreturn void *livstidsfange(void *arg) { size_t i = (size_t)arg; - unsigned harVippetBryter1 = 0U; - unsigned bryter1HarVartOppe = 0U; + bool harVippetBryter1 = false; + bool bryter1HarVartOppe = false; - unsigned forrigeGangErGyldig = 0U; - unsigned forrigeGang = 0U; + bool forrigeGangErGyldig = false; + bool forrigeGang = false; // Den tellende livstidsfangen kan allerede nå telle seg selv. if (i == tellendeLivstidsfange) { @@ -108,18 +118,18 @@ noreturn void *livstidsfange(void *arg) // Utføre selve simuleringen ved å sjekke brytere, m.m. antallBesok[i]++; - printf("livstidsfange %2zu har besøkt rommet %u ganger\n", i + 1, antallBesok[i]); + printf("livstidsfange %2zu har besøkt rommet %u gang%s\n", i + 1, antallBesok[i], antallBesok[i] == 1 ? "" : "er"); if (i == tellendeLivstidsfange) { - if (brytere[0] == 0U) { + if (brytere[0] == false) { printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1); - brytere[0] = 1U; + brytere[0] = true; } // if else { brytere[0] = !brytere[0]; - printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == 1U ? "opp" : "ned"); + printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned"); - if (forrigeGangErGyldig == 1U && forrigeGang == 0U) { + if (forrigeGangErGyldig == true && forrigeGang == false) { antallLivstidsfanger++; printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger); @@ -127,44 +137,40 @@ noreturn void *livstidsfange(void *arg) printf("livstidsfange %2zu avslutter simuleringen\n", i + 1); exit(0); } // if - } // if + } // if - forrigeGangErGyldig = 1U; + forrigeGangErGyldig = true; forrigeGang = brytere[0]; } // else } // if else { // Vanlig livstidsfange. - if (brytere[0] == 1U) { - printf("livstidsfange %2zu ser at bryter 1 er oppe, mens bryter 2 er %s\n", i + 1, brytere[1] == 1U ? "oppe" : "nede"); - bryter1HarVartOppe = 1U; + if (brytere[0] == true) { + printf("livstidsfange %2zu ser at bryter 1 er oppe, mens bryter 2 er %s\n", i + 1, brytere[1] == true ? "oppe" : "nede"); + bryter1HarVartOppe = true; brytere[1] = !brytere[1]; - printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == 1U ? "opp" : "ned"); + printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned"); } // if else { - printf("livstidsfange %2zu ser at bryter 1 er nede, mens bryter 2 er %s\n", i + 1, brytere[1] == 1U ? "oppe" : "nede"); + printf("livstidsfange %2zu ser at bryter 1 er nede, mens bryter 2 er %s\n", i + 1, brytere[1] == true ? "oppe" : "nede"); - if (harVippetBryter1 == 0U && bryter1HarVartOppe == 1U) { + if (harVippetBryter1 == false && bryter1HarVartOppe == true) { brytere[0] = !brytere[0]; - printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == 1U ? "opp" : "ned"); + printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned"); - harVippetBryter1 = 1U; - } // if + harVippetBryter1 = true; + } // if else { brytere[1] = !brytere[1]; - printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == 1U ? "opp" : "ned"); - } // else + printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned"); + } // else } // else } // else - // Signalere fengselsdirektøren (eller en vilkårlig livstidsfange). + // Tusle ut av rommet. printf("livstidsfange %2zu låser opp mutex\n", i + 1); pthread_mutex_unlock(&mutex); printf("livstidsfange %2zu har låst opp mutex\n", i + 1); - - printf("livstidsfange %2zu signalerer de andre trådene\n", i + 1); - pthread_cond_signal(&cond); - printf("livstidsfange %2zu har gitt signal til de andre trådene\n", i + 1); } // while } // livstidsfange() @@ -174,14 +180,15 @@ void visResultater(void) fflush(stderr); fflush(stdout); - fflush(stderr); - fflush(stdout); - puts(""); - printf("livstidsfange %2zu er den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1); + puts("\nResultater:\n"); + printf("bryter %u er ved avslutning vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned"); + printf("bryter %u er ved avslutning vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned"); + printf("livstidsfange %2zu var den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1); + for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) { - printf("livstidsfange %2zu: antall besøk = %u\n", i + 1, antallBesok[i]); + printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]); } // for fflush(stdout); @@ -191,8 +198,7 @@ void signalhandler(int sig) void signalhandler(int sig) { if (sig == SIGINT) { - visResultater(); - _exit(1); + exit(1); } // if } // signalhandler()