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

Contents of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations) (download)
2014-11-09T15:15:31Z (10 years ago) by trond
Content type: text/plain
File size: 6744 byte(s)
Det er bedre å referere til 2001-versjonen.

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