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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations) (download)
2014-11-19T19:32:53Z (10 years ago) by trond
Content type: text/plain
File size: 6920 byte(s)
Det er greit å frigjøre CPU-en etter én runde i fangetråden.

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