Advertisement
Guest User

Untitled

a guest
Sep 11th, 2019
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.20 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <semaphore.h>
  4. #include <pthread.h>
  5. #include <signal.h>
  6.  
  7. int* buffer;
  8. int* remaining_consumers;
  9. int* reader_position;
  10. static volatile int total_writers = 0, total_readers = 0;
  11. static volatile int next_pos_write = 0;
  12. int buff_length;
  13. int* ID;
  14. pthread_t* TID;
  15.  
  16. static volatile int next_produced_num = 0;
  17.  
  18. sem_t *sem_critical; // regiao crítica
  19. sem_t *sem_r, *sem_w; // controle de leitura e escrita
  20.  
  21. static volatile int delayed_r = 0, delayed_w = 0;
  22. static volatile int keep_alive = 1;
  23.  
  24. void iniciabuffer( int numpos, int numprod, int numcons )
  25. {
  26.   buff_length = numpos;
  27.   total_writers = numprod;
  28.   total_readers = numcons;
  29.  
  30.   // Alocação dinâmica
  31.   buffer = (int*) malloc( buff_length * sizeof(int) );
  32.   remaining_consumers = (int*) malloc(buff_length * sizeof(int));          
  33.   reader_position = (int*) malloc(total_readers * sizeof(int));
  34.   ID = (int*) malloc( (total_readers + total_writers ) * sizeof(int) );
  35.   TID = (pthread_t*) malloc( (total_readers + total_writers ) * sizeof( pthread_t) );
  36.   if( remaining_consumers == NULL || reader_position == NULL || buffer == NULL || ID == NULL || TID == NULL )
  37.   {
  38.     printf("Falha na alocacao dinamica de memoria\n");
  39.     return;
  40.   }
  41.  
  42.   // Inicialização vetores auxiliares
  43.   for (int i = 0; i < (total_readers + total_writers); ++i) ID[i] = i;
  44.   for (int i = 0; i < buff_length; i++) remaining_consumers[i] = 0;
  45.   for (int i = 0; i < total_readers; i++) reader_position[i] = 0;
  46. }
  47.  
  48. void pass_baton(int current_position) {
  49.   if (delayed_r > 0 &&
  50.       remaining_consumers[ current_position ] > 0 &&
  51.       (current_position != next_pos_write || remaining_consumers[ current_position ] == total_readers))
  52.     {
  53.       delayed_r--;
  54.       sem_post(sem_r); // passa o bastão para delayed reader
  55.     }
  56.     else if (delayed_w > 0 && remaining_consumers[ next_pos_write ] == 0)
  57.     {
  58.       delayed_w--;
  59.       sem_post(sem_w); // passa o bastão para delayed writer
  60.     }
  61.     else sem_post(sem_critical);
  62. }
  63.  
  64. /*
  65. MODELAGEM
  66.  < await (remaining_consumers[next_pos_write] == 0)
  67.      buffer[next_pos_write] = item
  68.      next_pos_write = ( next_pos_write + 1 ) % buff_length; >
  69. */
  70. void* deposita( void* id_ptr )
  71. {
  72.  
  73.   while( keep_alive )
  74.   {
  75.     sem_wait(sem_critical); // espera pra entrar na regiao critica
  76.    
  77.     int current_id = *( (int*) id_ptr );
  78.    
  79.     if (remaining_consumers[ next_pos_write ] != 0)
  80.     {
  81.       delayed_w++;
  82.       sem_post(sem_critical); // sai regiao critica
  83.       sem_wait(sem_w); // espera receber sinal para escrever
  84.     }
  85.    
  86.     printf("Escritor de id = %d, escreveu %d na posicao do buffer = %d\n\n", current_id, next_produced_num, next_pos_write );
  87.     buffer[next_pos_write] = next_produced_num++;
  88.     remaining_consumers[next_pos_write] = total_readers;
  89.     next_pos_write = ( next_pos_write + 1 ) % buff_length;
  90.    
  91.     // para fins de teste
  92.     if( next_produced_num == 20 )
  93.     {
  94.       keep_alive = 0;
  95.     }
  96.  
  97.     int current_position = reader_position[ current_id ];
  98.     pass_baton(current_position);
  99.   }
  100.   return NULL;
  101. }
  102.  
  103. /*
  104. MODELAGEM
  105.  < await (remaining_consumers[ current_position ] > 0 &&
  106.          (current_position != next_pos_write || remaining_consumers[ current_position ] == total_readers))
  107.    remaining_consumers[ current_position ]--;
  108.    reader_position[ current_id ] = nxt_position; >
  109.  
  110. A primeira condição do await garante que existe algo para consumir
  111. A segunda condição garante que um consumidor não consuma um item destinado
  112. a outro consumidor (isso pode acontecer se o buffer estiver cheio e um consumidor
  113. dispara na frente dos outros, e consome o item de um consumidor atrasado).
  114. */
  115. void* consome( void* id_ptr )
  116. {
  117.   while( keep_alive )
  118.   {
  119.     sem_wait(sem_critical); // espera pra entrar na regiao critica
  120.    
  121.     int current_id = *( (int*) id_ptr );
  122.     int current_position = reader_position[ current_id ];
  123.     int nxt_position = ( current_position + 1 ) % buff_length;
  124.  
  125.    
  126.     // Se o buffer estiver cheio: remaining_consumers[ next_pos_write ] > 0
  127.     // Caso contrário: remaining_consumers[ next_pos_write ] == 0
  128.     if (remaining_consumers[ current_position ] == 0 && // não tem nada para ler
  129.      
  130.       // Se estamos testando a segunda condição, sabemos que
  131.       // remaining_consumers[ current_position ] != 0
  132.       // Se current_position == next_pos_write e remaining_consumers[ current_position ] != 0
  133.       // sabemos que o buffer está cheio.
  134.       // Se remaining_consumers[ current_position ] == total_readers, nenhum consumidor
  135.       // consumiu o item atual. Caso contrário, o consumidor deu a volta no buffer
  136.       // e não pode mais consumir, se não ele vai consumir o mesmo item duas vezes
  137.         (current_position == next_pos_write &&
  138.         remaining_consumers[ current_position ] != total_readers))
  139.     {
  140.       delayed_r++;
  141.       sem_post(sem_critical); // sai regiao critica
  142.       sem_wait(sem_r); // espera receber sinal para continuar leitura
  143.     }
  144.  
  145.     printf("leitor %d leu o valor %d na posicao %d do buffer\n\n", current_id, buffer[current_position], current_position );
  146.     remaining_consumers[ current_position ]--;
  147.     reader_position[ current_id ] = nxt_position;
  148.     current_position = nxt_position;
  149.  
  150.     pass_baton(current_position);
  151.   }
  152.   return NULL;
  153. }
  154.  
  155. int main()
  156. {
  157.   sem_w = sem_open("/sem_w", O_CREAT, 0644, 0);
  158.   sem_r = sem_open("/sem_r", O_CREAT, 0644, 0);
  159.   sem_critical = sem_open("/sem_critical", O_CREAT, 0644, 1);
  160.  
  161.   // vamos fazer um caso simples, com 10 posicoes de buffer, 2 escritores e 2 leitores
  162.   iniciabuffer(10, 2, 2);
  163.  
  164.   for(int i = 0; i < total_readers; ++i)
  165.   {
  166.     printf("Criando o leitor de indice = %d\n\n", i );
  167.     pthread_create( &TID[i], NULL, consome , (void *) &ID[i] );
  168.  
  169.   }
  170.   for(int j = total_readers; j < total_readers + total_writers; ++j)
  171.   {
  172.     printf("Criando o escritor de indice = %d\n\n", j );
  173.     pthread_create( &TID[j], NULL, deposita ,  (void *) &ID[j] );
  174.   }
  175.  
  176.   int total = total_readers + total_writers;
  177.  
  178.   for(int i = 0; i < total; ++i)
  179.   {
  180.     pthread_join( TID[i], NULL );
  181.   }
  182.  
  183.   sem_unlink("/sem_w");
  184.   sem_unlink("/sem_r");
  185.   sem_unlink("/sem_critical");
  186.  
  187.   return 0;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement