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