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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (hide annotations) (download)
2014-11-09T15:30:18Z (9 years, 4 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 trond 13 // Programmet bruker ISO C 2011 (ISO/IEC 9899:2011) og Pthreads (IEEE Std 1003.1c-2001). -*- 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 trond 12 #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 trond 3 #include <errno.h>
11     #include <pthread.h>
12     #include <signal.h>
13 trond 5 #include <stdbool.h>
14 trond 3 #include <stdio.h>
15     #include <stdlib.h>
16     #include <string.h>
17 trond 9 #include <time.h>
18 trond 3 #include <unistd.h>
19    
20 trond 14 #if _POSIX_THREADS < 200112L
21     #error her mangler det støtte for POSIX Threads anno 2001
22     #endif
23    
24 trond 3 #if __STDC_VERSION__ >= 201112L
25     #include <stdnoreturn.h>
26     #else
27 trond 4 #define noreturn
28 trond 3 #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 trond 5 static bool brytere[2U];
40 trond 3
41     noreturn void *livstidsfange(void *arg);
42     void visResultater(void);
43     void signalhandler(int sig);
44    
45 trond 4 noreturn int main(int argc, char **argv)
46 trond 3 {
47     size_t i;
48 trond 4 pthread_t tid = pthread_self();
49 trond 3
50 trond 12 if (argc >= 0) { // Bare for å få clang til å ti stille.
51     atexit(visResultater);
52     signal(SIGINT, signalhandler);
53     } // if
54 trond 3
55 trond 9 #ifdef __FreeBSD__
56 trond 3 srandomdev();
57 trond 9 #else
58     srandom((unsigned int)time(NULL));
59     #endif
60 trond 3
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 trond 7 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 trond 3 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 trond 4 if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
79 trond 11 fflush(stdout);
80 trond 3 fprintf(stderr,
81     "%s: pthread_create(&tid, NULL, livstidsfange, (void *)%2zu) = %s (%d)\n",
82     argv[0], i, strerror(errno), errno);
83 trond 11 fflush(stderr);
84 trond 10 _exit(1);
85 trond 3 } // 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 trond 5 bool harVippetBryter1 = false;
109     bool bryter1HarVartOppe = false;
110 trond 3
111 trond 5 bool forrigeGangErGyldig = false;
112     bool forrigeGang = false;
113 trond 3
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 trond 7 printf("livstidsfange %2zu har besøkt rommet %u gang%s\n", i + 1, antallBesok[i], antallBesok[i] == 1 ? "" : "er");
132 trond 3
133     if (i == tellendeLivstidsfange) {
134 trond 5 if (brytere[0] == false) {
135 trond 3 printf("livstidsfange %2zu ser at bryter 1 er nede og vipper opp bryter 1\n", i + 1);
136 trond 5 brytere[0] = true;
137 trond 3 } // if
138     else {
139     brytere[0] = !brytere[0];
140 trond 8 printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned");
141 trond 3
142 trond 5 if (forrigeGangErGyldig == true && forrigeGang == false) {
143 trond 3 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 trond 4 } // if
151 trond 3
152 trond 5 forrigeGangErGyldig = true;
153 trond 3 forrigeGang = brytere[0];
154     } // else
155     } // if
156     else { // Vanlig livstidsfange.
157 trond 5 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 trond 3
161     brytere[1] = !brytere[1];
162 trond 5 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");
163 trond 3 } // if
164     else {
165 trond 5 printf("livstidsfange %2zu ser at bryter 1 er nede, mens bryter 2 er %s\n", i + 1, brytere[1] == true ? "oppe" : "nede");
166 trond 3
167 trond 5 if (harVippetBryter1 == false && bryter1HarVartOppe == true) {
168 trond 3 brytere[0] = !brytere[0];
169 trond 5 printf("livstidsfange %2zu vipper %s bryter 1\n", i + 1, brytere[0] == true ? "opp" : "ned");
170 trond 3
171 trond 5 harVippetBryter1 = true;
172 trond 4 } // if
173 trond 3 else {
174     brytere[1] = !brytere[1];
175 trond 5 printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == true ? "opp" : "ned");
176 trond 4 } // else
177 trond 3 } // else
178     } // else
179    
180 trond 4 // Tusle ut av rommet.
181 trond 3 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 trond 11
194 trond 7 puts("\nResultater:\n");
195 trond 3
196 trond 7 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 trond 3
200     for (i = 0; i < ANTALL_LIVSTIDSFANGER; i++) {
201 trond 7 printf("livstidsfange %2zu: antall besøk: %u\n", i + 1, antallBesok[i]);
202 trond 3 } // for
203 trond 12 puts("");
204 trond 3
205 trond 12 printf("antall livstidsfanger talt av den tellende livstidsfangen er %u\n", antallLivstidsfanger);
206    
207 trond 3 fflush(stdout);
208     fflush(stdout);
209     } // visResultater()
210    
211     void signalhandler(int sig)
212     {
213     if (sig == SIGINT) {
214 trond 4 exit(1);
215 trond 3 } // 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