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

Diff of /trunk/livstidsfanger.c

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

Revision 3 by trond, 2014-11-07T07:51:12Z Revision 4 by trond, 2014-11-07T07:56:17Z
# Line 2  Line 2 
2  // Løsning laget av Trond Endrestøl <Trond.Endrestol@ximalas.info>, 2014-11-06.  // Løsning laget 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 <stdio.h>  #include <stdio.h>
10  #include <stdlib.h>  #include <stdlib.h>
11  #include <string.h>  #include <string.h>
12  #include <unistd.h>  #include <unistd.h>
13    
14  #if __STDC_VERSION__ >= 201112L  #if __STDC_VERSION__ >= 201112L
15  #include <stdnoreturn.h>  #include <stdnoreturn.h>
16  #else  #else
17  #define noreturn /**/  #define noreturn
18  #endif  #endif
19    
20  #define ANTALL_LIVSTIDSFANGER 19U  #define ANTALL_LIVSTIDSFANGER 19U
21    
22  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];
23    
24  static size_t tellendeLivstidsfange;  static size_t tellendeLivstidsfange;
25  static unsigned antallLivstidsfanger;  static unsigned antallLivstidsfanger;
26    
27  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
28  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
   
 // Ingen må forandre på bryterne uten å ha låst mutex først.  
29  static unsigned brytere[2U];  static unsigned brytere[2U];
30    
31  noreturn void *livstidsfange(void *arg);  noreturn void *livstidsfange(void *arg);
32  void visResultater(void);  void visResultater(void);
33  void signalhandler(int sig);  void signalhandler(int sig);
34    
35  noreturn int main (int argc, char **argv)  noreturn int main(int argc, char **argv)
36  {  {
37    size_t i;    size_t i;
38    pthread_t tid = 0;    pthread_t tid = pthread_self();
39    
40    atexit(visResultater);    atexit(visResultater);
41    signal(SIGINT, signalhandler);    signal(SIGINT, signalhandler);
42    
43    srandomdev();    srandomdev();
44    
45    memset((void *)&antallBesok, 0, sizeof(antallBesok));    memset((void *)&antallBesok, 0, sizeof(antallBesok));
46    brytere[0] = random() & 1;    brytere[0] = random() & 1;
47    brytere[1] = random() & 1;    brytere[1] = random() & 1;
48    
49    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;
50    
51    puts("maintråden venter på å få låst mutex");    puts("maintråden venter på å få låst mutex");
52    pthread_mutex_lock(&mutex);    pthread_mutex_lock(&mutex);
53    puts("mutex er låst av maintråden");    puts("mutex er låst av maintråden");
54    
55    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
56      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);
57    
58      if ( ( errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {      if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
59        fprintf(stderr,        fprintf(stderr,
60                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",
61                argv[0], i, strerror(errno), errno);                argv[0], i, strerror(errno), errno);
62        exit(1);        exit(1);
63      } // if      } // if
64    } // for    } // for
65    
66    // maintråden påtar seg rolla som fengselsdirektøren.    // maintråden påtar seg rolla som fengselsdirektøren.
67    while (1) {    while (1) {
68      puts("fengselsdirektøren låser opp mutex");      puts("fengselsdirektøren låser opp mutex");
69      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
70      puts("mutex er låst opp av fengselsdirektøren");      puts("mutex er låst opp av fengselsdirektøren");
71    
72      puts("fengselsdirektøren signalerer livstidsfangene");      puts("fengselsdirektøren signalerer livstidsfangene");
73      pthread_cond_signal(&cond);      pthread_cond_signal(&cond);
# Line 101  noreturn void *livstidsfange(void *arg) Line 99  noreturn void *livstidsfange(void *arg)
99      printf("livstidsfange %2zu venter på å få låst mutex\n", i + 1);      printf("livstidsfange %2zu venter på å få låst mutex\n", i + 1);
100      pthread_mutex_lock(&mutex);      pthread_mutex_lock(&mutex);
101      printf("livstidsfange %2zu har låst mutex\n", i + 1);      printf("livstidsfange %2zu har låst mutex\n", i + 1);
102    
103      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);
104      pthread_cond_wait(&cond, &mutex);      pthread_cond_wait(&cond, &mutex);
105      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);
106    
107      // Utføre selve simuleringen ved å sjekke brytere, m.m.      // Utføre selve simuleringen ved å sjekke brytere, m.m.
108      antallBesok[i]++;      antallBesok[i]++;
109      printf("livstidsfange %2zu har besøkt rommet %u ganger\n", i + 1, antallBesok[i]);      printf("livstidsfange %2zu har besøkt rommet %u ganger\n", i + 1, antallBesok[i]);
110    
111      if (i == tellendeLivstidsfange) {      if (i == tellendeLivstidsfange) {
112        if (brytere[0] == 0U) {        if (brytere[0] == 0U) {
113          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);
114          brytere[0] = 1U;          brytere[0] = 1U;
115        } // if        } // if
116        else {        else {
117          brytere[0] = !brytere[0];          brytere[0] = !brytere[0];
118          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] == 1U ? "opp" : "ned");
119    
120          if (forrigeGangErGyldig == 1U && forrigeGang == 0U) {          if (forrigeGangErGyldig == 1U && forrigeGang == 0U) {
121            antallLivstidsfanger++;            antallLivstidsfanger++;
122            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);
123    
124            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {
125              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);
126              exit(0);              exit(0);
127            } // if            } // if
128          } // if          } // if
129    
130          forrigeGangErGyldig = 1U;          forrigeGangErGyldig = 1U;
131          forrigeGang = brytere[0];          forrigeGang = brytere[0];
132        } // else        } // else
133      } // if      } // if
134      else { // Vanlig livstidsfange.      else { // Vanlig livstidsfange.
135        if (brytere[0] == 1U) {        if (brytere[0] == 1U) {
136          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] == 1U ? "oppe" : "nede");
137          bryter1HarVartOppe = 1U;          bryter1HarVartOppe = 1U;
138    
139          brytere[1] = !brytere[1];          brytere[1] = !brytere[1];
140          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] == 1U ? "opp" : "ned");
141        } // if        } // if
142        else {        else {
143          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] == 1U ? "oppe" : "nede");
144    
145          if (harVippetBryter1 == 0U && bryter1HarVartOppe == 1U) {          if (harVippetBryter1 == 0U && bryter1HarVartOppe == 1U) {
146            brytere[0] = !brytere[0];            brytere[0] = !brytere[0];
147            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] == 1U ? "opp" : "ned");
148    
149            harVippetBryter1 = 1U;            harVippetBryter1 = 1U;
150          } // if          } // if
151          else {          else {
152            brytere[1] = !brytere[1];            brytere[1] = !brytere[1];
153            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] == 1U ? "opp" : "ned");
154          } // else          } // else
155        } // else        } // else
156      } // else      } // else
157    
158      // Signalere fengselsdirektøren (eller en vilkårlig livstidsfange).      // Tusle ut av rommet.
159      printf("livstidsfange %2zu låser opp mutex\n", i + 1);      printf("livstidsfange %2zu låser opp mutex\n", i + 1);
160      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
161      printf("livstidsfange %2zu har låst opp mutex\n", i + 1);      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);  
162    } // while    } // while
163  } // livstidsfange()  } // livstidsfange()
164    
165  void visResultater(void)  void visResultater(void)
166  {  {
167    size_t i;    size_t i;
168    
169    fflush(stderr);    fflush(stderr);
170    fflush(stdout);    fflush(stdout);
171    fflush(stderr);    fflush(stderr);
172    fflush(stdout);    fflush(stdout);
173    puts("");    puts("");
174    
175    printf("livstidsfange %2zu er den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);    printf("livstidsfange %2zu er den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);
176    
177    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
178      printf("livstidsfange %2zu: antall besøk = %u\n", i + 1, antallBesok[i]);      printf("livstidsfange %2zu: antall besøk = %u\n", i + 1, antallBesok[i]);
179    } // for    } // for
180    
181    fflush(stdout);    fflush(stdout);
182    fflush(stdout);    fflush(stdout);
183  } // visResultater()  } // visResultater()
184    
185  void signalhandler(int sig)  void signalhandler(int sig)
186  {  {
187    if (sig == SIGINT) {    if (sig == SIGINT) {
188      visResultater();      exit(1);
     _exit(1);  
189    } // if    } // if
190  } // signalhandler()  } // signalhandler()
191    
192  // 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