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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations) (download)
2014-11-07T07:56:17Z (10 years 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 trond 3 // 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 trond 4 #define noreturn
18 trond 3 #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 trond 4 noreturn int main(int argc, char **argv)
36 trond 3 {
37     size_t i;
38 trond 4 pthread_t tid = pthread_self();
39 trond 3
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 trond 4 if ( (errno = pthread_create(&tid, NULL, livstidsfange, (void *)i)) != 0) {
59 trond 3 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 trond 4 brytere[0] = 1U;
115 trond 3 } // 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 trond 4 } // if
129 trond 3
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 trond 4 } // if
151 trond 3 else {
152     brytere[1] = !brytere[1];
153     printf("livstidsfange %2zu vipper %s bryter 2\n", i + 1, brytere[1] == 1U ? "opp" : "ned");
154 trond 4 } // else
155 trond 3 } // else
156     } // else
157    
158 trond 4 // Tusle ut av rommet.
159 trond 3 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 trond 4 exit(1);
189 trond 3 } // 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