Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include "pthread.h"
- #include "semaphore.h"
- typedef struct GlobalState {
- pthread_mutex_t ActMutex;
- int iFanPerType[2];
- int MustJoinCaptain;
- int FansRemaining;
- int iWantPerType[2];
- pthread_t aFanCarThread[4];
- sem_t WantFanType[2];
- pthread_barrier_t JoinTheCar;
- sem_t DoneSemaphore;
- } GlobalState;
- GlobalState g_tState;
- void *FanThread(void *arg) {
- int n, iFan = (int)arg, iFansInCar;
- pthread_t tid = pthread_self();
- //show the looking for message right after thread creation
- //pthread_mutex_lock(&g_tState.ActMutex);
- //printf("Thread ID: %014lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);
- //pthread_mutex_unlock(&g_tState.ActMutex);
- while (1) {
- sem_wait( &g_tState.WantFanType[iFan] );
- pthread_mutex_lock(&g_tState.ActMutex);
- g_tState.iWantPerType[iFan]=0;
- //clean up last captain thread if any
- if (g_tState.MustJoinCaptain) {
- pthread_join(g_tState.aFanCarThread[3], NULL );
- g_tState.MustJoinCaptain = 0;
- }
- //number of fans on car is #A + #B
- iFansInCar = g_tState.iFanPerType[0]+g_tState.iFanPerType[1];
- //allowed combinatios are 2:2 or 4:0
- if ((iFansInCar < 3) || (g_tState.iFanPerType[iFan] & 1)) {
- //set the TID for this fan on a car slot (so we can wait & cleanup)
- g_tState.aFanCarThread[iFansInCar] = tid;
- g_tState.iFanPerType[iFan]++;
- //if there still not 3, then we still accept either
- if (iFansInCar < 2 ) {
- if (!g_tState.iWantPerType[0]) { g_tState.iWantPerType[0]=1 ; sem_post( &g_tState.WantFanType[0] ); }
- if (!g_tState.iWantPerType[1]) { g_tState.iWantPerType[1]=1 ; sem_post( &g_tState.WantFanType[1] ); }
- } else if (iFansInCar == 2) {
- n = (g_tState.iFanPerType[0] & 1) ? 0 : 1;
- if (!g_tState.iWantPerType[n]) { g_tState.iWantPerType[n]=1 ; sem_post( &g_tState.WantFanType[n] ); }
- g_tState.iWantPerType[1-n]=0;
- }
- printf("Thread ID: %014lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);
- // wait for 4 compatible fans to arrive before entering the car
- pthread_mutex_unlock(&g_tState.ActMutex);
- pthread_barrier_wait( &g_tState.JoinTheCar );
- pthread_mutex_lock(&g_tState.ActMutex);
- printf("Thread ID: %014lli, Team: %c, I have found a spot in a car\n",tid,'A'+iFan);
- pthread_mutex_unlock(&g_tState.ActMutex);
- //if this fan will fill a car, then it becomes the captain and a car is finished
- if (iFansInCar==3) {
- //so then we can "join" the previous 3 fan threads that finished (thread cleanup)
- for (n=0 ; n<iFansInCar ; n++) {
- pthread_join(g_tState.aFanCarThread[n], NULL );
- }
- pthread_mutex_lock(&g_tState.ActMutex);
- printf("Thread ID: %014lli, Team: %c, I am the captain and driving the car\n",tid,'A'+iFan);
- g_tState.iFanPerType[0] = g_tState.iFanPerType[1] = 0;
- g_tState.MustJoinCaptain = 1; g_tState.FansRemaining -= 4;
- if (!g_tState.FansRemaining) { sem_post( &g_tState.DoneSemaphore ); }
- // new car... accepts both
- if (!g_tState.iWantPerType[0]) { g_tState.iWantPerType[0]=1 ; sem_post( &g_tState.WantFanType[0] ); }
- if (!g_tState.iWantPerType[1]) { g_tState.iWantPerType[1]=1 ; sem_post( &g_tState.WantFanType[1] ); }
- pthread_mutex_unlock(&g_tState.ActMutex);
- }
- //fan is inside a car so exit the thread
- break;
- } else {
- // spurious wake?
- //if (!g_tState.iWantPerType[1-n]) { g_tState.iWantPerType[1-n]=1 ; sem_post( &g_tState.WantFanType[1-n] ); }
- pthread_mutex_unlock(&g_tState.ActMutex);
- }
- }
- }
- void ManageThreads(int iNumA,int iNumB) {
- int i;
- pthread_t tid;
- //number of fans on each group must be even
- if ((iNumA & 1) || (iNumB & 1)) return;
- //total number must be a multiple of 4
- if ((iNumA+iNumB) & 3) return;
- //initialize global state
- g_tState.FansRemaining = iNumA+iNumB;
- g_tState.MustJoinCaptain = 0;
- pthread_mutex_init(&g_tState.ActMutex, NULL);
- sem_init(&g_tState.WantFanType[0],0,1);
- sem_init(&g_tState.WantFanType[1],0,1);
- g_tState.iWantPerType[0] = 1;
- g_tState.iWantPerType[1] = 1;
- pthread_barrier_init(&g_tState.JoinTheCar, NULL, 4);
- sem_init(&g_tState.DoneSemaphore, 0, 0);
- // creating threads
- for ( i=0 ; i<iNumA ; i++ ) {
- while (pthread_create(&tid, NULL, &FanThread, (void*)0)) { };
- }
- for ( i=0 ; i<iNumB ; i++ ) {
- while (pthread_create(&tid, NULL, &FanThread, (void*)1)) { };
- }
- //waiting for all fans to depart
- sem_wait( &g_tState.DoneSemaphore );
- //waiting for last thread to finish
- pthread_join(g_tState.aFanCarThread[3], NULL );
- //free resources
- pthread_barrier_destroy(&g_tState.JoinTheCar);
- sem_destroy(&g_tState.DoneSemaphore);
- pthread_mutex_destroy(&g_tState.ActMutex);
- sem_destroy(&g_tState.WantFanType[0]);
- sem_destroy(&g_tState.WantFanType[1]);
- }
- int main(int argc, char *argv[]) {
- int iNumA,iNumB;
- //number of arguments must be 3...
- //ProgramName , FansA , FansB
- if (argc == 3) {
- //fans of different members
- iNumA = atoi(argv[1]);
- iNumB = atoi(argv[2]);
- ManageThreads( iNumA , iNumB );
- }
- puts("main terminates");
- getchar();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement