View difference between Paste ID: BQFcnXeT and WrBPJ0iZ
SHOW: | | - or go back to the newest paste.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include "pthread.h"
4
#include "semaphore.h"
5
6
typedef struct GlobalState {
7
	pthread_mutex_t   ActMutex;
8
	int               iFanPerType[2];
9-
	int               MustJoinCaptain;
9+
	int               MustJoinCaptain;	
10
	int               FansRemaining;
11-
	pthread_t         aFanCarThread[4];
11+
	int               iWantPerType[2];
12-
	pthread_mutex_t   BeginNewCar;
12+
	pthread_t         aFanCarThread[4];	
13
	sem_t             WantFanType[2];
14-
	sem_t             QueueLimit;
14+
15
	sem_t             DoneSemaphore;
16
} GlobalState;
17
18
GlobalState g_tState;
19
	
20
void *FanThread(void *arg) {
21
	int n, iFan = (int)arg, iFansInCar;
22
	pthread_t tid = pthread_self();	
23
		
24-
	//limited exit from the event...
24+
25-
	sem_wait( &g_tState.QueueLimit );	
25+
	//pthread_mutex_lock(&g_tState.ActMutex);
26
  //printf("Thread ID: %014lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);	
27
	//pthread_mutex_unlock(&g_tState.ActMutex);
28-
	pthread_mutex_lock(&g_tState.ActMutex);
28+
29-
  printf("Thread ID: %lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);	
29+
	while (1) { 		  	  
30-
	pthread_mutex_unlock(&g_tState.ActMutex);
30+
		sem_wait( &g_tState.WantFanType[iFan] );
31
		
32-
	while (1) { 	
32+
		pthread_mutex_lock(&g_tState.ActMutex);
33-
	  pthread_mutex_lock(&g_tState.ActMutex);		
33+
		g_tState.iWantPerType[iFan]=0;
34
								
35
	  //clean up last captain thread if any
36
		if (g_tState.MustJoinCaptain) {
37
		  pthread_join(g_tState.aFanCarThread[3], NULL );
38
			g_tState.MustJoinCaptain = 0;
39
	  }
40
		//number of fans on car is #A + #B
41
		iFansInCar = g_tState.iFanPerType[0]+g_tState.iFanPerType[1];		
42-
		if ((iFansInCar < 3) || (g_tState.iFanPerType[iFan] & 1)) {			
42+
				
43
		//allowed combinatios are 2:2 or 4:0
44
		if ((iFansInCar < 3) || (g_tState.iFanPerType[iFan] & 1)) {					  
45
      //set the TID for this fan on a car slot (so we can wait & cleanup)
46
			g_tState.aFanCarThread[iFansInCar] = tid;
47-
			//printf("Thread ID: %lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);	
47+
48
			
49
			//if there still not 3, then we still accept either
50
			if (iFansInCar < 2 ) {
51
			  if (!g_tState.iWantPerType[0]) { g_tState.iWantPerType[0]=1 ; sem_post( &g_tState.WantFanType[0] ); }
52-
			//pthread_mutex_trylock(&g_tState.BeginNewCar);
52+
			  if (!g_tState.iWantPerType[1]) { g_tState.iWantPerType[1]=1 ; sem_post( &g_tState.WantFanType[1] ); }				
53
			} else if (iFansInCar == 2) {
54
				n = (g_tState.iFanPerType[0] & 1) ? 0 : 1;				
55-
      pthread_mutex_trylock(&g_tState.BeginNewCar);			
55+
				if (!g_tState.iWantPerType[n]) { g_tState.iWantPerType[n]=1 ; sem_post( &g_tState.WantFanType[n] ); }				
56-
			printf("Thread ID: %lli, Team: %c, I have found a spot in a car\n",tid,'A'+iFan);	
56+
				g_tState.iWantPerType[1-n]=0;
57
		  }
58
					
59
			printf("Thread ID: %014lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);				
60
			
61
			// wait for 4 compatible fans to arrive before entering the car
62-
					pthread_join(g_tState.aFanCarThread[n], NULL );
62+
63
			pthread_barrier_wait( &g_tState.JoinTheCar );						
64
						
65-
				printf("Thread ID: %lli, Team: %c, I am the captain and driving the car\n",tid,'A'+iFan);
65+
66
			printf("Thread ID: %014lli, Team: %c, I have found a spot in a car\n",tid,'A'+iFan);						
67-
				g_tState.MustJoinCaptain = 1;
67+
68-
				g_tState.FansRemaining -= 4;
68+
69
			//if this fan will fill a car, then it becomes the captain and a car is finished
70-
				pthread_mutex_unlock(&g_tState.ActMutex);
70+
71-
				pthread_mutex_unlock(&g_tState.BeginNewCar);
71+
72-
				//when finishing a car a new one can start...				
72+
73
					pthread_join(g_tState.aFanCarThread[n], NULL );					
74
				}				
75
				pthread_mutex_lock(&g_tState.ActMutex);			
76
				printf("Thread ID: %014lli, Team: %c, I am the captain and driving the car\n",tid,'A'+iFan);
77-
			//printf("Thread ID: %lli, Team: %c, waiting for a new car...\n",tid,'A'+iFan);
77+
78
				g_tState.MustJoinCaptain = 1; g_tState.FansRemaining -= 4;				
79-
			//wait for a new car
79+
80-
			pthread_mutex_lock(&g_tState.BeginNewCar);
80+
				
81-
			pthread_mutex_unlock(&g_tState.BeginNewCar);			
81+
				// new car... accepts both				
82
				if (!g_tState.iWantPerType[0]) { g_tState.iWantPerType[0]=1 ; sem_post( &g_tState.WantFanType[0] ); }
83
			  if (!g_tState.iWantPerType[1]) { g_tState.iWantPerType[1]=1 ; sem_post( &g_tState.WantFanType[1] ); }
84
				
85-
	//allow more people to exit.
85+
				pthread_mutex_unlock(&g_tState.ActMutex);				
86-
	sem_post( &g_tState.QueueLimit );	
86+
				
87
			}
88
			//fan is inside a car so exit the thread			
89
			break;
90
		} else {			
91
		  // spurious wake?
92
			//if (!g_tState.iWantPerType[1-n]) { g_tState.iWantPerType[1-n]=1 ; sem_post( &g_tState.WantFanType[1-n] ); }			
93
			pthread_mutex_unlock(&g_tState.ActMutex);			
94
		}
95
	}
96
	
97
}
98
99
void ManageThreads(int iNumA,int iNumB) {
100
	
101-
	g_tState.FansRemaining = iNumA+iNumB;
101+
102
	pthread_t tid;
103-
	pthread_mutex_init(&g_tState.ActMutex, NULL);	
103+
104-
	pthread_mutex_init(&g_tState.BeginNewCar, NULL);	
104+
105-
	//pthread_mutex_lock(&g_tState.BeginNewCar);
105+
106
	//total number must be a multiple of 4
107
	if ((iNumA+iNumB) & 3) return;	
108-
	sem_init(&g_tState.QueueLimit, 0, 6);
108+
109
	//initialize global state
110
	g_tState.FansRemaining = iNumA+iNumB;	
111
	g_tState.MustJoinCaptain = 0;
112-
    pthread_create(&tid, NULL, &FanThread, (void*)0);	
112+
	pthread_mutex_init(&g_tState.ActMutex, NULL);		
113
	sem_init(&g_tState.WantFanType[0],0,1);	
114
	sem_init(&g_tState.WantFanType[1],0,1);	
115
	g_tState.iWantPerType[0] = 1;
116-
    pthread_create(&tid, NULL, &FanThread, (void*)1);	
116+
	g_tState.iWantPerType[1] = 1;
117
	
118
	pthread_barrier_init(&g_tState.JoinTheCar, NULL, 4);	
119
	sem_init(&g_tState.DoneSemaphore, 0, 0);
120
	
121
	// creating threads
122
	for ( i=0 ; i<iNumA ; i++ ) {
123
    while (pthread_create(&tid, NULL, &FanThread, (void*)0)) { };	
124
	}	
125
	
126
	for ( i=0 ; i<iNumB ; i++ ) {
127-
	sem_destroy(&g_tState.QueueLimit);
127+
    while (pthread_create(&tid, NULL, &FanThread, (void*)1)) { };	
128-
	pthread_mutex_destroy(&g_tState.ActMutex);
128+
129-
	pthread_mutex_destroy(&g_tState.BeginNewCar);
129+
130
	//waiting for all fans to depart
131
	sem_wait( &g_tState.DoneSemaphore );	
132
	//waiting for last thread to finish
133
	pthread_join(g_tState.aFanCarThread[3], NULL );	
134
	
135
	//free resources
136
	pthread_barrier_destroy(&g_tState.JoinTheCar);	
137
	sem_destroy(&g_tState.DoneSemaphore);
138
	pthread_mutex_destroy(&g_tState.ActMutex);	
139
	sem_destroy(&g_tState.WantFanType[0]);
140
	sem_destroy(&g_tState.WantFanType[1]);
141
	
142
}
143
144
int main(int argc, char *argv[]) {
145
	int iNumA,iNumB;
146
		
147
	//number of arguments must be 3...
148
	//ProgramName , FansA , FansB
149
	if (argc == 3) {	
150
		//fans of different members
151
		iNumA = atoi(argv[1]);
152
		iNumB = atoi(argv[2]);	
153
	  ManageThreads( iNumA , iNumB );
154
	}
155
			
156
	puts("main terminates");	
157
	getchar();
158
	return 0;
159
}
160