Advertisement
Guest User

Untitled

a guest
Dec 17th, 2018
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.66 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <semaphore.h>
  5. #include <math.h>
  6.  
  7. #define PHILOSOPHERS_COUNT 5
  8. #define THINKING 1
  9. #define HUNGRY 2
  10. #define EATING 3
  11.  
  12. #define EATINGS_LIMIT 2 // лимит обедов
  13.  
  14. #define MAX_THINKING_TIME 5 // максимальное время на размышления в сек
  15. #define MAX_EATING_TIME 5 // максимальное время на обед в сек
  16.  
  17.  
  18. typedef struct {
  19.     uint8_t num; // номер философа
  20.     sem_t* forks; // семафоры-вилки
  21.     int* state; // массив состояний философов
  22. } PhilThreadParams;
  23.  
  24. pthread_mutex_t printf_mutex; // мьютекс для printf
  25. pthread_mutex_t states_mutex; // мьютекс для массива состояний
  26.  
  27. void print_forks_stats(PhilThreadParams* params)
  28. {
  29.     int i;
  30.     pthread_mutex_lock(&printf_mutex);
  31.     printf("FORKS {");
  32.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  33.         printf("%d:", i);
  34.         int sval = 0;
  35.         sem_getvalue(&params->forks[i], &sval);
  36.         if(sval == 0) {
  37.             printf("in use");
  38.         } else {
  39.             printf("free");
  40.         }
  41.  
  42.         if (i != PHILOSOPHERS_COUNT - 1) {
  43.             printf(", ");
  44.         }
  45.     }
  46.     printf("}\n");
  47.     pthread_mutex_unlock(&printf_mutex);
  48. }
  49.  
  50. void print_philosophers_stats(PhilThreadParams* params)
  51. {
  52.     int i;
  53.     pthread_mutex_lock(&printf_mutex);
  54.     printf("PHILOSOPHERS {");
  55.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  56.         printf("%d:", i);
  57.         pthread_mutex_lock(&states_mutex);
  58.         switch (params->state[i])
  59.         {
  60.         case THINKING:
  61.             printf("THINKING");
  62.             break;
  63.         case HUNGRY:
  64.             printf("HUNGRY");
  65.             break;
  66.         case EATING:
  67.             printf("EATING");
  68.             break;
  69.         }
  70.         pthread_mutex_unlock(&states_mutex);
  71.  
  72.         if (i != PHILOSOPHERS_COUNT - 1) {
  73.             printf(", ");
  74.         }
  75.     }
  76.     printf("}\n");
  77.     pthread_mutex_unlock(&printf_mutex);
  78. }
  79.  
  80.  
  81. // функуия размышлений
  82. void think(PhilThreadParams* params)
  83. {
  84.     int thinking_time = rand() % MAX_THINKING_TIME; // генерируем время размышлений
  85.     pthread_mutex_lock(&printf_mutex);
  86.     printf("Philosopher %d thinking for %d seconds\n", params->num, thinking_time);
  87.     pthread_mutex_unlock(&printf_mutex);
  88.     sleep(thinking_time); // думаем
  89.     pthread_mutex_lock(&states_mutex);
  90.     params->state[params->num] = HUNGRY; // философ проголодался
  91.     pthread_mutex_unlock(&states_mutex);
  92. }
  93.  
  94. // функция официанта
  95. void waiter(PhilThreadParams* params) {
  96.  
  97.     int left = params->num;
  98.     int right = (params->num + 1) % PHILOSOPHERS_COUNT;
  99.  
  100.     sem_wait(&params->forks[left]);
  101.     printf("Philosopher %d take fork #%d\n", params->num, left);
  102.     // берем вторую вилку
  103.     sem_wait(&params->forks[right]);
  104.     printf("Philosopher %d take fork #%d\n", params->num, right);
  105.  
  106.     pthread_mutex_lock(&states_mutex);
  107.     params->state[params->num] = EATING; // взяли вилки
  108.     pthread_mutex_unlock(&states_mutex);
  109. }
  110.  
  111. // функция обеда
  112. void eating(PhilThreadParams* params)
  113. {
  114.     int eating_time = rand() % MAX_EATING_TIME; // генерируем время обеда
  115.     pthread_mutex_lock(&printf_mutex);
  116.     printf("Philosopher %d eating for %d seconds\n", params->num, eating_time);
  117.     pthread_mutex_unlock(&printf_mutex);
  118.     sleep(eating_time); // обедаем
  119. }
  120.  
  121. // кладем вилки
  122. void put_forks(PhilThreadParams* params) {
  123.     int left = params->num;
  124.     int right = (params->num + 1) % PHILOSOPHERS_COUNT;
  125.  
  126.     sem_post(&params->forks[left]);
  127.     printf("Philosopher %d put fork #%d\n", params->num, left);
  128.     sem_post(&params->forks[right]);
  129.     printf("Philosopher %d put fork #%d\n", params->num, right);
  130.     pthread_mutex_lock(&states_mutex);
  131.     params->state[params->num] = THINKING; // философ наелся, можно думать
  132.     pthread_mutex_unlock(&states_mutex);
  133. }
  134.  
  135. // функция потока философа
  136. void philosopher_thread(PhilThreadParams* params)
  137. {
  138.     int eatings_count = 0;
  139.  
  140.     pthread_mutex_lock(&printf_mutex);
  141.     printf("PHILOSHPER %d HELLO\n", params->num);
  142.     pthread_mutex_unlock(&printf_mutex);
  143.  
  144.     while (1) {
  145.         print_philosophers_stats(params);
  146.         think(params);
  147.         waiter(params);
  148.         eating(params);
  149.         put_forks(params);
  150.  
  151.     eatings_count++;
  152.     if (eatings_count == EATINGS_LIMIT) {
  153.         break;
  154.     }
  155.     }
  156.  
  157.     pthread_mutex_lock(&printf_mutex);
  158.     printf("PHILOSHPER %d BYE\n", params->num);
  159.     pthread_mutex_unlock(&printf_mutex);
  160.     pthread_exit(NULL);
  161. }
  162.  
  163. int main(int argc, char *argv[]) {
  164.     sem_t forks[PHILOSOPHERS_COUNT];
  165.     int phil_states[PHILOSOPHERS_COUNT];
  166.     PhilThreadParams params[PHILOSOPHERS_COUNT];
  167.     int i;
  168.  
  169.     // инициализируем мьютексы
  170.     pthread_mutex_init(&printf_mutex, NULL);
  171.     pthread_mutex_init(&states_mutex, NULL);
  172.  
  173.     pthread_mutex_lock(&printf_mutex);
  174.     printf("Main thread start\n");
  175.     pthread_mutex_unlock(&printf_mutex);
  176.  
  177.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  178.         sem_init(&forks[i], 0, 1); // инициализация семафора
  179.         phil_states[i] = THINKING;
  180.     }
  181.  
  182.     pthread_t philosophers_threads[PHILOSOPHERS_COUNT];
  183.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  184.         params[i].num = i;
  185.         params[i].forks = forks;
  186.         params[i].state = phil_states;
  187.         pthread_create(&philosophers_threads[i], NULL, philosopher_thread, &params[i]);
  188.     }
  189.  
  190.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  191.         pthread_join(philosophers_threads[i], NULL);
  192.     }
  193.  
  194.     for (i = 0 ; i < PHILOSOPHERS_COUNT ; i++) {
  195.         sem_destroy(&forks[i]); // уничтожение семафора
  196.     }
  197.  
  198.     pthread_mutex_lock(&printf_mutex);
  199.     printf("Main thread end\n");
  200.     pthread_mutex_unlock(&printf_mutex);
  201.  
  202.     // уничтожаем мьютексы
  203.     pthread_mutex_destroy(printf_mutex);
  204.     pthread_mutex_destroy(states_mutex);
  205.  
  206.     return EXIT_SUCCESS;
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement