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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations) (download)
2014-11-07T13:50:02Z (9 years, 11 months ago) by trond
Content type: text/plain
File size: 6417 byte(s)
Det er en fordel at vi ikke setter i gang atexit()-registrerte
funksjoner når vi får problemer med pthread_create() og må avslutte.

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

Properties

Name Value
svn:eol-style native
svn:keywords Ximalas=%H
svn:mime-type text/plain

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