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

Contents of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations) (download)
2014-11-07T07:56:17Z (6 years, 11 months ago) by trond
Content type: text/plain
File size: 5747 byte(s)
Gjorde om litt whitespace.
Initialiserer tid med pthread_self() bare for å få clang til å ti stille.
Livstidsfangene trenger ikke å signalere noen som helst.
signalhandler() kan kalle på exit() istedet for _exit(), og la alle funksjoner registrert med atexit() bli kjørt.
Fjernet noen skjønnhetsfeil.

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