Advertisement
Mysoft

Untitled

Apr 27th, 2021
1,165
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.     int               iWantPerType[2];
  12.     pthread_t         aFanCarThread[4];
  13.     sem_t             WantFanType[2];
  14.     pthread_barrier_t JoinTheCar;  
  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.     //show the looking for message right after thread creation
  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.        
  29.     while (1) {              
  30.         sem_wait( &g_tState.WantFanType[iFan] );
  31.        
  32.         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.                
  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.             g_tState.iFanPerType[iFan]++;
  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.               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.                 if (!g_tState.iWantPerType[n]) { g_tState.iWantPerType[n]=1 ; sem_post( &g_tState.WantFanType[n] ); }              
  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_mutex_unlock(&g_tState.ActMutex);          
  63.             pthread_barrier_wait( &g_tState.JoinTheCar );                      
  64.                        
  65.             pthread_mutex_lock(&g_tState.ActMutex);
  66.             printf("Thread ID: %014lli, Team: %c, I have found a spot in a car\n",tid,'A'+iFan);                       
  67.             pthread_mutex_unlock(&g_tState.ActMutex);
  68.            
  69.             //if this fan will fill a car, then it becomes the captain and a car is finished
  70.             if (iFansInCar==3) {               
  71.                 //so then we can "join" the previous 3 fan threads that finished (thread cleanup)              
  72.                 for (n=0 ; n<iFansInCar ; n++) {
  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.                 g_tState.iFanPerType[0] = g_tState.iFanPerType[1] = 0;
  78.                 g_tState.MustJoinCaptain = 1; g_tState.FansRemaining -= 4;             
  79.                 if (!g_tState.FansRemaining) { sem_post( &g_tState.DoneSemaphore ); }
  80.                
  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.                 pthread_mutex_unlock(&g_tState.ActMutex);              
  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.     int i;
  102.     pthread_t tid;
  103.    
  104.   //number of fans on each group must be even
  105.     if ((iNumA & 1) || (iNumB & 1)) return;
  106.     //total number must be a multiple of 4
  107.     if ((iNumA+iNumB) & 3) return; 
  108.    
  109.     //initialize global state
  110.     g_tState.FansRemaining = iNumA+iNumB;  
  111.     g_tState.MustJoinCaptain = 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.     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.     while (pthread_create(&tid, NULL, &FanThread, (void*)1)) { };  
  128.     }
  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.    
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement