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

Diff of /trunk/livstidsfanger.c

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

Revision 7 by trond, 2014-11-07T08:56:07Z Revision 15 by trond, 2014-11-19T19:32:53Z
# 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-2001). -*- coding: utf-8 -*-
2  // Løsning programmert 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    #if __STDC_VERSION__ < 199901L
7    #error det er tvilsomt om du får kompilert denne kildekoden med så gammel C-kompilator
8    #endif
9    
10  #include <errno.h>  #include <errno.h>
11  #include <pthread.h>  #include <pthread.h>
12    #include <sched.h>
13  #include <signal.h>  #include <signal.h>
14  #include <stdbool.h>  #include <stdbool.h>
15  #include <stdio.h>  #include <stdio.h>
16  #include <stdlib.h>  #include <stdlib.h>
17  #include <string.h>  #include <string.h>
18    #include <time.h>
19  #include <unistd.h>  #include <unistd.h>
20    
21    #if _POSIX_THREADS < 200112L
22    #error her mangler det støtte for POSIX Threads anno 2001
23    #endif
24    
25  #if __STDC_VERSION__ >= 201112L  #if __STDC_VERSION__ >= 201112L
26  #include <stdnoreturn.h>  #include <stdnoreturn.h>
27  #else  #else
28  #define noreturn  #define noreturn
29  #endif  #endif
30    
31  #define ANTALL_LIVSTIDSFANGER 19U  #define ANTALL_LIVSTIDSFANGER 19U
32    
33  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];  static unsigned antallBesok[ANTALL_LIVSTIDSFANGER];
34    
35  static size_t tellendeLivstidsfange;  static size_t tellendeLivstidsfange;
36  static unsigned antallLivstidsfanger;  static unsigned antallLivstidsfanger;
37    
38  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
39  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
40  static bool brytere[2U];  static bool brytere[2U];
41    
42  noreturn void *livstidsfange(void *arg);  noreturn void *livstidsfange(void *arg);
43  void visResultater(void);  void visResultater(void);
44  void signalhandler(int sig);  void signalhandler(int sig);
45    
46  noreturn int main(int argc, char **argv)  noreturn int main(int argc, char **argv)
47  {  {
48    size_t i;    size_t i;
49    pthread_t tid = pthread_self();    pthread_t tid = pthread_self();
50    
51    atexit(visResultater);    if (argc >= 0) { // Bare for å få clang til å ti stille.
52    signal(SIGINT, signalhandler);      atexit(visResultater);
53        signal(SIGINT, signalhandler);
54      } // if
55    
56    #ifdef __FreeBSD__
57    srandomdev();    srandomdev();
58    #else
59      srandom((unsigned int)time(NULL));
60    #endif
61    
62    memset((void *)&antallBesok, 0, sizeof(antallBesok));    memset((void *)&antallBesok, 0, sizeof(antallBesok));
63    brytere[0] = random() & 1;    brytere[0] = random() & 1;
64    brytere[1] = random() & 1;    brytere[1] = random() & 1;
65    
66    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;    tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;
67    
68    printf("bryter %u er i utgangspunktet vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");    printf("bryter %u er i utgangspunktet vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");
69    printf("bryter %u er i utgangspunktet vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");    printf("bryter %u er i utgangspunktet vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");
70    printf("livstidsfange %zu er utpekt som den tellende livstidsfange\n\n", tellendeLivstidsfange + 1);    printf("livstidsfange %zu er utpekt som den tellende livstidsfange\n\n", tellendeLivstidsfange + 1);
71    
72    puts("maintråden venter på å få låst mutex");    puts("maintråden venter på å få låst mutex");
73    pthread_mutex_lock(&mutex);    pthread_mutex_lock(&mutex);
74    puts("mutex er låst av maintråden");    puts("mutex er låst av maintråden");
75    
76    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
77      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);      printf("maintråden oppretter livstidsfange %2zu\n", i + 1);
78    
79      if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {      if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
80          fflush(stdout);
81        fprintf(stderr,        fprintf(stderr,
82                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",                "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",
83                argv[0], i, strerror(errno), errno);                argv[0], i, strerror(errno), errno);
84        exit(1);        fflush(stderr);
85          _exit(1);
86      } // if      } // if
87    } // for    } // for
88    
89    // maintråden påtar seg rolla som fengselsdirektøren.    // maintråden påtar seg rolla som fengselsdirektøren.
90    while (1) {    while (1) {
91      puts("fengselsdirektøren låser opp mutex");      puts("fengselsdirektøren låser opp mutex");
92      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
93      puts("mutex er låst opp av fengselsdirektøren");      puts("mutex er låst opp av fengselsdirektøren");
94    
95      puts("fengselsdirektøren signalerer livstidsfangene");      puts("fengselsdirektøren signalerer livstidsfangene");
96      pthread_cond_signal(&cond);      pthread_cond_signal(&cond);
97      puts("signal er sendt fra fengselsdirektøren");      puts("signal er sendt fra fengselsdirektøren");
98    
99      puts("fengselsdirektøren venter på å få låst mutex");      puts("fengselsdirektøren venter på å få låst mutex");
100      pthread_mutex_lock(&mutex);      pthread_mutex_lock(&mutex);
# Line 108  noreturn void *livstidsfange(void *arg) Line 126  noreturn void *livstidsfange(void *arg)
126      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);      printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);
127      pthread_cond_wait(&cond, &mutex);      pthread_cond_wait(&cond, &mutex);
128      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);
129    
130      // Utføre selve simuleringen ved å sjekke brytere, m.m.      // Utføre selve simuleringen ved å sjekke brytere, m.m.
131      antallBesok[i]++;      antallBesok[i]++;
132      printf("livstidsfange %2zu har besøkt rommet %u gang%s\n", i + 1, antallBesok[i], antallBesok[i] == 1 ? "" : "er");      printf("livstidsfange %2zu har besøkt rommet %u gang%s\n", i + 1, antallBesok[i], antallBesok[i] == 1 ? "" : "er");
133    
134      if (i == tellendeLivstidsfange) {      if (i == tellendeLivstidsfange) {
135        if (brytere[0] == false) {        if (brytere[0] == false) {
136          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);
137          brytere[0] = true;          brytere[0] = true;
138        } // if        } // if
139        else {        else {
140          brytere[0] = !brytere[0];          brytere[0] = !brytere[0];
141          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");
142    
143          if (forrigeGangErGyldig == true && forrigeGang == false) {          if (forrigeGangErGyldig == true && forrigeGang == false) {
144            antallLivstidsfanger++;            antallLivstidsfanger++;
145            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);            printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);
146    
147            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {            if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {
148              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);              printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);
149              exit(0);              exit(0);
150            } // if            } // if
151          } // if          } // if
152    
153          forrigeGangErGyldig = true;          forrigeGangErGyldig = true;
154          forrigeGang = brytere[0];          forrigeGang = brytere[0];
155        } // else        } // else
156      } // if      } // if
# Line 152  noreturn void *livstidsfange(void *arg) Line 170  noreturn void *livstidsfange(void *arg)
170            printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned");            printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned");
171    
172            harVippetBryter1 = true;            harVippetBryter1 = true;
173          } // if          } // if
174          else {          else {
175            brytere[1] = !brytere[1];            brytere[1] = !brytere[1];
176            printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");            printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");
177          } // else          } // else
178        } // else        } // else
179      } // else      } // else
180    
181      // Tusle ut av rommet.      // Tusle ut av rommet.
182      printf("livstidsfange %2zu låser opp mutex\n", i + 1);      printf("livstidsfange %2zu låser opp mutex\n", i + 1);
183      pthread_mutex_unlock(&mutex);      pthread_mutex_unlock(&mutex);
184      printf("livstidsfange %2zu har låst opp mutex\n", i + 1);      printf("livstidsfange %2zu har låst opp mutex\n", i + 1);
185    
186    #ifdef _POSIX_PRIORITY_SCHEDULING
187        sched_yield();
188    #endif
189    } // while    } // while
190  } // livstidsfange()  } // livstidsfange()
191    
192  void visResultater(void)  void visResultater(void)
193  {  {
194    size_t i;    size_t i;
195    
196    fflush(stderr);    fflush(stderr);
197    fflush(stdout);    fflush(stdout);
198    fflush(stderr);  
   fflush(stdout);  
199    puts("\nResultater:\n");    puts("\nResultater:\n");
200    
201    printf("bryter %u er ved avslutning vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");    printf("bryter %u er ved avslutning vippet %s\n", 1U, brytere[0] == true ? "opp" : "ned");
202    printf("bryter %u er ved avslutning vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");    printf("bryter %u er ved avslutning vippet %s\n", 2U, brytere[1] == true ? "opp" : "ned");
203    printf("livstidsfange %2zu var den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);    printf("livstidsfange %2zu var den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);
204    
205    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {    for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
206      printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]);      printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]);
207    } // for    } // for
208      puts("");
209    
210      printf("antall livstidsfanger talt av den tellende livstidsfangen er %u\n", antallLivstidsfanger);
211    
212    fflush(stdout);    fflush(stdout);
213    fflush(stdout);    fflush(stdout);
214  } // visResultater()  } // visResultater()
215    
216  void signalhandler(int sig)  void signalhandler(int sig)
217  {  {
218    if (sig == SIGINT) {    if (sig == SIGINT) {
219      exit(1);      exit(1);
220    } // if    } // if
221  } // signalhandler()  } // signalhandler()
222    
223  // 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