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

Contents of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations) (download)
2014-11-07T08:56:07Z (9 years, 4 months ago) by trond
Content type: text/plain
File size: 6327 byte(s)
Dytta inn beskrivelser av tilstanden i forkant og etterkant av simuleringen.

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