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

Contents of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations) (download)
2014-11-07T07:51:12Z (10 years ago) by trond
Content type: text/plain
File size: 6035 byte(s)
Inn med trunk/BSDmakefile og trunk/livstidsfanger.c.

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
30 // Ingen må forandre på bryterne uten å ha låst mutex først.
31 static unsigned brytere[2U];
32
33 noreturn void *livstidsfange(void *arg);
34 void visResultater(void);
35 void signalhandler(int sig);
36
37 noreturn int main (int argc, char **argv)
38 {
39 size_t i;
40 pthread_t tid = 0;
41
42 atexit(visResultater);
43 signal(SIGINT, signalhandler);
44
45 srandomdev();
46
47 memset((void *)&antallBesok, 0, sizeof(antallBesok));
48 brytere[0] = random() & 1;
49 brytere[1] = random() & 1;
50
51 tellendeLivstidsfange = random() % ANTALL_LIVSTIDSFANGER;
52
53 puts("maintråden venter på å få låst mutex");
54 pthread_mutex_lock(&mutex);
55 puts("mutex er låst av maintråden");
56
57 for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
58 printf("maintråden oppretter livstidsfange %2zu\n", i + 1);
59
60 if ( ( errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
61 fprintf(stderr,
62 "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",
63 argv[0], i, strerror(errno), errno);
64 exit(1);
65 } // if
66 } // for
67
68 // maintråden påtar seg rolla som fengselsdirektøren.
69 while (1) {
70 puts("fengselsdirektøren låser opp mutex");
71 pthread_mutex_unlock(&mutex);
72 puts("mutex er låst opp av fengselsdirektøren");
73
74 puts("fengselsdirektøren signalerer livstidsfangene");
75 pthread_cond_signal(&cond);
76 puts("signal er sendt fra fengselsdirektøren");
77
78 puts("fengselsdirektøren venter på å få låst mutex");
79 pthread_mutex_lock(&mutex);
80 puts("mutex er låst av fengselsdirektøren");
81 } // while
82 } // main()
83
84 noreturn void *livstidsfange(void *arg)
85 {
86 size_t i = (size_t)arg;
87
88 unsigned harVippetBryter1 = 0U;
89 unsigned bryter1HarVartOppe = 0U;
90
91 unsigned forrigeGangErGyldig = 0U;
92 unsigned forrigeGang = 0U;
93
94 // Den tellende livstidsfangen kan allerede nå telle seg selv.
95 if (i == tellendeLivstidsfange) {
96 antallLivstidsfanger++;
97 } // if
98
99 while (1) {
100 // Vente på tur.
101 printf("livstidsfange %2zu venter på å få låst mutex\n", i + 1);
102 pthread_mutex_lock(&mutex);
103 printf("livstidsfange %2zu har låst mutex\n", i + 1);
104
105 printf("livstidsfange %2zu venter på signal fra fengselsdirektøren\n", i + 1);
106 pthread_cond_wait(&cond, &mutex);
107 printf("livstidsfange %2zu har fått signal fra fengselsdirektøren og har låst mutex\n", i + 1);
108
109 // Utføre selve simuleringen ved å sjekke brytere, m.m.
110 antallBesok[i]++;
111 printf("livstidsfange %2zu har besøkt rommet %u ganger\n", i + 1, antallBesok[i]);
112
113 if (i == tellendeLivstidsfange) {
114 if (brytere[0] == 0U) {
115 printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1);
116 brytere[0] = 1U;
117 } // if
118 else {
119 brytere[0] = !brytere[0];
120 printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == 1U ? "opp" : "ned");
121
122 if (forrigeGangErGyldig == 1U && forrigeGang == 0U) {
123 antallLivstidsfanger++;
124 printf("livstidsfange %2zu har talt opp %u livstidsfanger\n", i + 1, antallLivstidsfanger);
125
126 if (antallLivstidsfanger == ANTALL_LIVSTIDSFANGER) {
127 printf("livstidsfange %2zu avslutter simuleringen\n", i + 1);
128 exit(0);
129 } // if
130 } // if
131
132 forrigeGangErGyldig = 1U;
133 forrigeGang = brytere[0];
134 } // else
135 } // if
136 else { // Vanlig livstidsfange.
137 if (brytere[0] == 1U) {
138 printf("livstidsfange %2zu ser at bryter 1 er oppe, mens bryter 2 er %s\n", i + 1, brytere[1] == 1U ? "oppe" : "nede");
139 bryter1HarVartOppe = 1U;
140
141 brytere[1] = !brytere[1];
142 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == 1U ? "opp" : "ned");
143 } // if
144 else {
145 printf("livstidsfange %2zu ser at bryter 1 er nede, mens bryter 2 er %s\n", i + 1, brytere[1] == 1U ? "oppe" : "nede");
146
147 if (harVippetBryter1 == 0U && bryter1HarVartOppe == 1U) {
148 brytere[0] = !brytere[0];
149 printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == 1U ? "opp" : "ned");
150
151 harVippetBryter1 = 1U;
152 } // if
153 else {
154 brytere[1] = !brytere[1];
155 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == 1U ? "opp" : "ned");
156 } // else
157 } // else
158 } // else
159
160 // Signalere fengselsdirektøren (eller en vilkårlig livstidsfange).
161 printf("livstidsfange %2zu låser opp mutex\n", i + 1);
162 pthread_mutex_unlock(&mutex);
163 printf("livstidsfange %2zu har låst opp mutex\n", i + 1);
164
165 printf("livstidsfange %2zu signalerer de andre trådene\n", i + 1);
166 pthread_cond_signal(&cond);
167 printf("livstidsfange %2zu har gitt signal til de andre trådene\n", i + 1);
168 } // while
169 } // livstidsfange()
170
171 void visResultater(void)
172 {
173 size_t i;
174
175 fflush(stderr);
176 fflush(stdout);
177 fflush(stderr);
178 fflush(stdout);
179 puts("");
180
181 printf("livstidsfange %2zu er den tellende livstidsfangen\n\n", tellendeLivstidsfange + 1);
182
183 for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
184 printf("livstidsfange %2zu: antall besøk = %u\n", i + 1, antallBesok[i]);
185 } // for
186
187 fflush(stdout);
188 fflush(stdout);
189 } // visResultater()
190
191 void signalhandler(int sig)
192 {
193 if (sig == SIGINT) {
194 visResultater();
195 _exit(1);
196 } // if
197 } // signalhandler()
198
199 // 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