Advertisement
Mysoft

Untitled

Apr 26th, 2021
1,175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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;
  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.            
  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.    
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement