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

Annotation of /trunk/livstidsfanger.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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     #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