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

Contents of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (show annotations) (download)
2014-11-09T15:30:18Z (9 years, 11 months ago) by trond
Content type: text/plain
File size: 6840 byte(s)
Sjekke om systemet tilbyr i det minste pthreads anno 2001.
Pussig at makroen er definert i unistd.h og ikke i pthread.h.

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