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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide 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 trond 3 // Programmet bruker ISO C 2011 (ISO/IEC 9899:2011) og Pthreads (IEEE Std 1003.1c-1995). -*- coding: utf-8 -*-
2 trond 6 // Løsning programmert av Trond Endrestøl <Trond.Endrestol@ximalas.info>, 2014-11-06.
3 trond 3
4     // $Ximalas$
5    
6     #include <errno.h>
7     #include <pthread.h>
8     #include <signal.h>
9 trond 5 #include <stdbool.h>
10 trond 3 #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 trond 4 #define noreturn
19 trond 3 #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 trond 5 static bool brytere[2U];
31 trond 3
32     noreturn void *livstidsfange(void *arg);
33     void visResultater(void);
34     void signalhandler(int sig);
35    
36 trond 4 noreturn int main(int argc, char **argv)
37 trond 3 {
38     size_t i;
39 trond 4 pthread_t tid = pthread_self();
40 trond 3
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 trond 7 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 trond 3 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 trond 4 if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
64 trond 3 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 trond 5 bool harVippetBryter1 = false;
92     bool bryter1HarVartOppe = false;
93 trond 3
94 trond 5 bool forrigeGangErGyldig = false;
95     bool forrigeGang = false;
96 trond 3
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 trond 7 printf("livstidsfange %2zu har besøkt rommet %u gang%s\n", i + 1, antallBesok[i], antallBesok[i] == 1 ? "" : "er");
115 trond 3
116     if (i == tellendeLivstidsfange) {
117 trond 5 if (brytere[0] == false) {
118 trond 3 printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1);
119 trond 5 brytere[0] = true;
120 trond 3 } // 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 trond 5 if (forrigeGangErGyldig == true && forrigeGang == false) {
126 trond 3 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 trond 4 } // if
134 trond 3
135 trond 5 forrigeGangErGyldig = true;
136 trond 3 forrigeGang = brytere[0];
137     } // else
138     } // if
139     else { // Vanlig livstidsfange.
140 trond 5 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 trond 3
144     brytere[1] = !brytere[1];
145 trond 5 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");
146 trond 3 } // if
147     else {
148 trond 5 printf("livstidsfange %2zu ser at bryter 1 er nede, mens bryter 2 er %s\n", i + 1, brytere[1] == true ? "oppe" : "nede");
149 trond 3
150 trond 5 if (harVippetBryter1 == false && bryter1HarVartOppe == true) {
151 trond 3 brytere[0] = !brytere[0];
152 trond 5 printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned");
153 trond 3
154 trond 5 harVippetBryter1 = true;
155 trond 4 } // if
156 trond 3 else {
157     brytere[1] = !brytere[1];
158 trond 5 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");
159 trond 4 } // else
160 trond 3 } // else
161     } // else
162    
163 trond 4 // Tusle ut av rommet.
164 trond 3 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 trond 7 puts("\nResultater:\n");
179 trond 3
180 trond 7 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 trond 3
184     for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
185 trond 7 printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]);
186 trond 3 } // for
187    
188     fflush(stdout);
189     fflush(stdout);
190     } // visResultater()
191    
192     void signalhandler(int sig)
193     {
194     if (sig == SIGINT) {
195 trond 4 exit(1);
196 trond 3 } // 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