/[livstidsfanger]/trunk/livstidsfanger.c
ViewVC logotype

Diff of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 4 by trond, 2014-11-07T07:56:17Z Revision 11 by trond, 2014-11-08T11:56:59Z
# Line 1  Line 1 
1  // Programmet bruker ISO C 2011 (ISO/IEC 9899:2011) og Pthreads (IEEE Std 1003.1c-1995). -*- coding: utf-8 -*-  // Programmet bruker ISO C 2011 (ISO/IEC 9899:2011) og Pthreads (IEEE Std 1003.1c-1995). -*- coding: utf-8 -*-
2  // Løsning laget av Trond Endrestøl <Trond.Endrestol@ximalas.info>, 2014-11-06.  // Løsning programmert av Trond Endrestøl <Trond.Endrestol@ximalas.info>, 2014-11-06.
3    
4  // $Ximalas$  // $Ximalas$
5    
6  #include <errno.h>  #include <errno.h>
7  #include <pthread.h>  #include <pthread.h>
8  #include <signal.h>  #include <signal.h>
9    #include <stdbool.h>
10  #include <stdio.h>  #include <stdio.h>
11  #include <stdlib.h>  #include <stdlib.h>
12  #include <string.h>  #include <string.h>
13    #include <time.h>
14  #include <unistd.h>  #include <unistd.h>
15    
16  #if __STDC_VERSION__ >= 201112L  #if __STDC_VERSION__ >= 201112L
17  #include <stdnoreturn.h>  #include <stdnoreturn.h>
18  #else  #else
19  #define noreturn  #define noreturn
20  #endif  #endif
21    
22  #define ANTALL_LIVSTIDSFANGER 19U  #define ANTALL_LIVSTIDSFANGER 19U
23    
24  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];
25    
26  static size_t tellendeLivstidsfange;  static size_t tellendeLivstidsfange;
27  static unsigned antallLivstidsfanger;  static unsigned antallLivstidsfanger;
28    
29  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
30  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
31  static unsigned brytere[2U];  static bool brytere[2U];
32    
33  noreturn void *livstidsfange(void *arg);  noreturn void *livstidsfange(void *arg);
34  void visResultater(void);  void visResultater(void);
35  void signalhandler(int sig);  void signalhandler(int sig);
36    
37  noreturn int main(int argc, char **argv)  noreturn int main(int argc, char **argv)
38  {  {
39    size_t i;    size_t i;
40    pthread_t tid = pthread_self();    pthread_t tid = pthread_self();
41    
42    atexit(visResultater);    atexit(visResultater);
43    signal(SIGINT, signalhandler);    signal(SIGINT, signalhandler);
44    
45    #ifdef __FreeBSD__
46    srandomdev();    srandomdev();
47    #else
48      srandom((unsigned int)time(NULL));
49    #endif
50    
51    memset((void *)&antallBesok, 0, sizeof(antallBesok));    memset((void *)&antallBesok, 0, sizeof(antallBesok));
52    brytere[0] = random() & 1;    brytere[0] = random() & 1;
53    brytere[1] = random() & 1;    brytere[1] = random() & 1;
54    
55    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;
56    
57      printf("bryter %u er i utgangspunktet vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");
58      printf("bryter %u er i utgangspunktet vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");
59      printf("livstidsfange %zu er utpekt som den tellende livstidsfange\n\n", tellendeLivstidsfange + 1);
60    
61    puts("maintråden venter på å få låst mutex");    puts("maintråden venter på å få låst mutex");
62    pthread_mutex_lock(&mutex);    pthread_mutex_lock(&mutex);
63    puts("mutex er låst av maintråden");    puts("mutex er låst av maintråden");
64    
65    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
66      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);
67    
68      if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {      if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
69          fflush(stdout);
70        fprintf(stderr,        fprintf(stderr,
71                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",
72                argv[0], i, strerror(errno), errno);                argv[0], i, strerror(errno), errno);
73        exit(1);        fflush(stderr);
74          _exit(1);
75      } // if      } // if
76    } // for    } // for
77    
78    // maintråden påtar seg rolla som fengselsdirektøren.    // maintråden påtar seg rolla som fengselsdirektøren.
79    while (1) {    while (1) {
80      puts("fengselsdirektøren låser opp mutex");      puts("fengselsdirektøren låser opp mutex");
81      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
82      puts("mutex er låst opp av fengselsdirektøren");      puts("mutex er låst opp av fengselsdirektøren");
83    
84      puts("fengselsdirektøren signalerer livstidsfangene");      puts("fengselsdirektøren signalerer livstidsfangene");
85      pthread_cond_signal(&cond);      pthread_cond_signal(&cond);
86      puts("signal er sendt fra fengselsdirektøren");      puts("signal er sendt fra fengselsdirektøren");
87    
88      puts("fengselsdirektøren venter på å få låst mutex");      puts("fengselsdirektøren venter på å få låst mutex");
89      pthread_mutex_lock(&mutex);      pthread_mutex_lock(&mutex);
90      puts("mutex er låst av fengselsdirektøren");      puts("mutex er låst av fengselsdirektøren");
91    } // while    } // while
92  } // main()  } // main()
93    
94  noreturn void *livstidsfange(void *arg)  noreturn void *livstidsfange(void *arg)
95  {  {
96    size_t i = (size_t)arg;    size_t i = (size_t)arg;
97    
98    unsigned harVippetBryter1 = 0U;    bool harVippetBryter1 = false;
99    unsigned bryter1HarVartOppe = 0U;    bool bryter1HarVartOppe = false;
100    
101    unsigned forrigeGangErGyldig = 0U;    bool forrigeGangErGyldig = false;
102    unsigned forrigeGang = 0U;    bool forrigeGang = false;
103    
104    // Den tellende livstidsfangen kan allerede nå telle seg selv.    // Den tellende livstidsfangen kan allerede nå telle seg selv.
105    if (i == tellendeLivstidsfange) {    if (i == tellendeLivstidsfange) {
106      antallLivstidsfanger++;      antallLivstidsfanger++;
107    } // if    } // if
108    
109    while (1) {    while (1) {
110      // Vente på tur.      // Vente på tur.
111      printf("livstidsfange %2zu venter på å få låst mutex\n", i + 1);      printf("livstidsfange %2zu venter på å få låst mutex\n", i + 1);
112      pthread_mutex_lock(&mutex);      pthread_mutex_lock(&mutex);
113      printf("livstidsfange %2zu har låst mutex\n", i + 1);      printf("livstidsfange %2zu har låst mutex\n", i + 1);
114    
115      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);
116      pthread_cond_wait(&cond, &mutex);      pthread_cond_wait(&cond, &mutex);
117      printf("livstidsfange %2zu har fått signal fra fengselsdirektøren og har låst mutex\n", i + 1);      printf("livstidsfange %2zu har fått signal fra fengselsdirektøren og har låst mutex\n", i + 1);
118    
119      // Utføre selve simuleringen ved å sjekke brytere, m.m.      // Utføre selve simuleringen ved å sjekke brytere, m.m.
120      antallBesok[i]++;      antallBesok[i]++;
121      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");
122    
123      if (i == tellendeLivstidsfange) {      if (i == tellendeLivstidsfange) {
124        if (brytere[0] == 0U) {        if (brytere[0] == false) {
125          printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1);          printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1);
126          brytere[0] = 1U;          brytere[0] = true;
127        } // if        } // if
128        else {        else {
129          brytere[0] = !brytere[0];          brytere[0] = !brytere[0];
130          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");
131    
132          if (forrigeGangErGyldig == 1U && forrigeGang == 0U) {          if (forrigeGangErGyldig == true && forrigeGang == false) {
133            antallLivstidsfanger++;            antallLivstidsfanger++;
134            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);
135    
136            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {
137              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);
138              exit(0);              exit(0);
139            } // if            } // if
140          } // if          } // if
141    
142          forrigeGangErGyldig = 1U;          forrigeGangErGyldig = true;
143          forrigeGang = brytere[0];          forrigeGang = brytere[0];
144        } // else        } // else
145      } // if      } // if
146      else { // Vanlig livstidsfange.      else { // Vanlig livstidsfange.
147        if (brytere[0] == 1U) {        if (brytere[0] == true) {
148          printf("livstidsfange %2zu ser at bryter 1 er oppe, mens bryter 2 er %s\n", i + 1, brytere[1] == 1U ? "oppe" : "nede");          printf("livstidsfange %2zu ser at bryter 1 er oppe, mens bryter 2 er %s\n", i + 1, brytere[1] == true ? "oppe" : "nede");
149          bryter1HarVartOppe = 1U;          bryter1HarVartOppe = true;
150    
151          brytere[1] = !brytere[1];          brytere[1] = !brytere[1];
152          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");
153        } // if        } // if
154        else {        else {
155          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");
156    
157          if (harVippetBryter1 == 0U && bryter1HarVartOppe == 1U) {          if (harVippetBryter1 == false && bryter1HarVartOppe == true) {
158            brytere[0] = !brytere[0];            brytere[0] = !brytere[0];
159            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");
160    
161            harVippetBryter1 = 1U;            harVippetBryter1 = true;
162          } // if          } // if
163          else {          else {
164            brytere[1] = !brytere[1];            brytere[1] = !brytere[1];
165            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");
166          } // else          } // else
167        } // else        } // else
168      } // else      } // else
169    
170      // Tusle ut av rommet.      // Tusle ut av rommet.
171      printf("livstidsfange %2zu låser opp mutex\n", i + 1);      printf("livstidsfange %2zu låser opp mutex\n", i + 1);
172      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
173      printf("livstidsfange %2zu har låst opp mutex\n", i + 1);      printf("livstidsfange %2zu har låst opp mutex\n", i + 1);
174    } // while    } // while
175  } // livstidsfange()  } // livstidsfange()
176    
177  void visResultater(void)  void visResultater(void)
178  {  {
179    size_t i;    size_t i;
180    
181    fflush(stderr);    fflush(stderr);
182    fflush(stdout);    fflush(stdout);
   fflush(stderr);  
   fflush(stdout);  
   puts("");  
183    
184    printf("livstidsfange %2zu er den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);    puts("\nResultater:\n");
185    
186      printf("bryter %u er ved avslutning vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");
187      printf("bryter %u er ved avslutning vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");
188      printf("livstidsfange %2zu var den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);
189    
190    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
191      printf("livstidsfange %2zu: antall besøk = %u\n", i + 1, antallBesok[i]);      printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]);
192    } // for    } // for
193    
194    fflush(stdout);    fflush(stdout);
195    fflush(stdout);    fflush(stdout);
196  } // visResultater()  } // visResultater()
197    
198  void signalhandler(int sig)  void signalhandler(int sig)
199  {  {
200    if (sig == SIGINT) {    if (sig == SIGINT) {
201      exit(1);      exit(1);
202    } // if    } // if
203  } // signalhandler()  } // signalhandler()
204    
205  // livstidsfanger.c  // livstidsfanger.c


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

svn@ximalas.info
ViewVC Help
Powered by ViewVC 1.3.0-dev