Advertisement
Guest User

Untitled

a guest
Oct 21st, 2014
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.79 KB | None | 0 0
  1. #include <iostream>
  2. #include <pthread.h>
  3. #include <sys/types.h>
  4. #include <sys/ipc.h>
  5. #include <sys/msg.h>
  6. #include <pthread.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9.  
  10. // несколько потоков
  11. // переменные состояния для синхронизации
  12. // очереди сообщений для обмена инфой
  13. // вычисляем дисперсию
  14. using namespace std;
  15. #define MSGPERM 0600
  16. // переменные состояния
  17. pthread_cond_t  addCond = PTHREAD_COND_INITIALIZER,
  18.                 subCond = PTHREAD_COND_INITIALIZER,
  19.                 sqrCond = PTHREAD_COND_INITIALIZER,
  20.                 divCond = PTHREAD_COND_INITIALIZER,
  21.                 eEnd = PTHREAD_COND_INITIALIZER;
  22. // мьютекс для переменных состояния
  23. pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
  24.  
  25. // специальная переменная, описывающая, что сейчас надо делать
  26. enum {OP_NONE,OP_ADD, OP_EXIT, OP_SUB, OP_SQR, OP_DIV} cop = OP_NONE;
  27.  
  28. // идентификатор очереди сообщений
  29. int msqid;
  30.  
  31. // структура сообщения
  32. typedef struct{
  33.     public:
  34.         long mtype;
  35.         double a;
  36.         double b;
  37. } mymsgbuf;
  38.  
  39. // поток сложения
  40. void* addThread(void* arg)
  41. {
  42.     // буфер для хранения сообщения
  43.     mymsgbuf buf;
  44.    
  45.     // вечный цикл
  46.     while(true)
  47.     {
  48.         // блокируем мьютекс
  49.         pthread_mutex_lock(&mt);
  50.         // и начинаем ждать сигнала и одного из двух значений переменной cop
  51.         while((cop != OP_ADD)&&(cop != OP_EXIT))
  52.             pthread_cond_wait(&addCond, &mt);
  53.         // разблокируем мьютекс
  54.         pthread_mutex_unlock(&mt);
  55.         // если нужно выходить, то идём к выходу
  56.         if(cop == OP_EXIT)
  57.             break;
  58.         // принимаем сообщение
  59.         msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  60.         // выводим лог
  61.         cout << "[Adder]: " << buf.a << '+' << buf.b << endl;
  62.         // осуществляем сложение
  63.         buf.a = buf.a + buf.b;
  64.         // отсылаем результат
  65.         msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  66.         // блокируем мьютекс
  67.         pthread_mutex_lock(&mt);
  68.         // переменную cop в состояние "ничегонеделания"
  69.         cop = OP_NONE;
  70.         // будим основной поток
  71.         pthread_cond_signal(&eEnd);
  72.         // разблокируем мьютекс
  73.         pthread_mutex_unlock(&mt);
  74.     }
  75.     // выход из потока
  76.     pthread_exit(0);
  77. }
  78. // всё также, как и выше, но с вычитанием
  79. void* subThread(void* arg)
  80. {
  81.     mymsgbuf buf;
  82.  
  83.     while(true)
  84.     {
  85.         pthread_mutex_lock(&mt);
  86.         while((cop != OP_SUB)&&(cop != OP_EXIT))
  87.             pthread_cond_wait(&subCond, &mt);
  88.         pthread_mutex_unlock(&mt);
  89.         if(cop == OP_EXIT)
  90.             break;
  91.         msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  92.         cout << "[Subtractor]: " << buf.a << '-' << buf.b << endl;
  93.         buf.a = buf.a - buf.b;
  94.         msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  95.  
  96.         pthread_mutex_lock(&mt);
  97.         cop = OP_NONE;
  98.         pthread_cond_signal(&eEnd);
  99.         pthread_mutex_unlock(&mt);
  100.     }
  101.     cout << "OK2" << endl;
  102.     pthread_exit(0);
  103. }
  104. // аналогично, но с делением
  105. void* divThread(void* arg)
  106. {
  107.     mymsgbuf buf;
  108.  
  109.     while(true)
  110.     {
  111.         pthread_mutex_lock(&mt);
  112.         while((cop != OP_DIV)&&(cop != OP_EXIT))
  113.             pthread_cond_wait(&divCond, &mt);
  114.         pthread_mutex_unlock(&mt);
  115.         if(cop == OP_EXIT)
  116.             break;
  117.         msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  118.         cout << "[Divider]: " << buf.a << '/' << buf.b << endl;
  119.         buf.a = buf.a / buf.b;
  120.         msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  121.  
  122.         pthread_mutex_lock(&mt);
  123.         cop = OP_NONE;
  124.         pthread_cond_signal(&eEnd);
  125.         pthread_mutex_unlock(&mt);
  126.     }
  127.     cout << "OK2" << endl;
  128.     pthread_exit(0);
  129. }
  130. // аналогично, но с возведением в квадрат
  131. void* sqrThread(void* arg)
  132. {
  133.     mymsgbuf buf;
  134.  
  135.     while(true)
  136.     {
  137.         pthread_mutex_lock(&mt);
  138.         while((cop != OP_SQR)&&(cop != OP_EXIT))
  139.             pthread_cond_wait(&sqrCond, &mt);
  140.         pthread_mutex_unlock(&mt);
  141.         if(cop == OP_EXIT)
  142.             break;
  143.         msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  144.         cout << "[Squarer]: " << buf.a << "^2" << endl;
  145.         buf.a = buf.a * buf.a;
  146.         msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  147.  
  148.         pthread_mutex_lock(&mt);
  149.         cop = OP_NONE;
  150.         pthread_cond_signal(&eEnd);
  151.         pthread_mutex_unlock(&mt);
  152.     }
  153.     cout << "OK2" << endl;
  154.     pthread_exit(0);
  155. }
  156. // процедура для взаимодействия с потоком сложения
  157. double myadd(double a, double b)
  158. {
  159.     // буфер для хранения сообщения
  160.     mymsgbuf buf;
  161.     // инициализируем буфер нужными значениями
  162.     buf.a = a;
  163.     buf.b = b;
  164.     buf.mtype = 1;
  165.     // отсылаем сообщение
  166.     rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  167.     // блокирвем мьютекс
  168.     pthread_mutex_lock(&mt);
  169.     // устанавливаем действие "сложение"
  170.     cop = OP_ADD;
  171.     // будим слагательный поток
  172.     pthread_cond_signal(&addCond);
  173.     // разблокируем мьютекс
  174.     pthread_mutex_unlock(&mt);
  175.     // снова блокируем
  176.     pthread_mutex_lock(&mt);
  177.     // ждём, пока операция не выполнится
  178.     while(cop != OP_NONE)
  179.         pthread_cond_wait(&eEnd, &mt);
  180.     // разблокируем
  181.     pthread_mutex_unlock(&mt);
  182.     // принимаем ответ
  183.     msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  184.     // выдаем ответ
  185.     return buf.a;
  186. }
  187. // аналогично, как выше, но с вычитанием
  188. double mysub(double a, double b)
  189. {
  190.     mymsgbuf buf;
  191.     buf.a = a;
  192.     buf.b = b;
  193.     buf.mtype = 1;
  194.     rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  195.     pthread_mutex_lock(&mt);
  196.     cop = OP_SUB;
  197.     pthread_cond_signal(&subCond);
  198.     pthread_mutex_unlock(&mt);
  199.  
  200.     pthread_mutex_lock(&mt);
  201.     while(cop != OP_NONE)
  202.         pthread_cond_wait(&eEnd, &mt);
  203.     pthread_mutex_unlock(&mt);
  204.     msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  205.     return buf.a;
  206. }
  207. // аналогично, но с делением
  208. double mydiv(double a, double b)
  209. {
  210.     mymsgbuf buf;
  211.     buf.a = a;
  212.     buf.b = b;
  213.     buf.mtype = 1;
  214.     rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  215.     pthread_mutex_lock(&mt);
  216.     cop = OP_DIV;
  217.     pthread_cond_signal(&divCond);
  218.     pthread_mutex_unlock(&mt);
  219.  
  220.     pthread_mutex_lock(&mt);
  221.     while(cop != OP_NONE)
  222.         pthread_cond_wait(&eEnd, &mt);
  223.     pthread_mutex_unlock(&mt);
  224.     msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  225.     return buf.a;
  226. }
  227. // аналогично, но с возведением в квадрат
  228. double mysqr(double a)
  229. {
  230.     mymsgbuf buf;
  231.     buf.a = a;
  232.     buf.mtype = 1;
  233.     rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
  234.     pthread_mutex_lock(&mt);
  235.     cop = OP_SQR;
  236.     pthread_cond_signal(&sqrCond);
  237.     pthread_mutex_unlock(&mt);
  238.  
  239.     pthread_mutex_lock(&mt);
  240.     while(cop != OP_NONE)
  241.         pthread_cond_wait(&eEnd, &mt);
  242.     pthread_mutex_unlock(&mt);
  243.     msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
  244.     return buf.a;
  245. }
  246.  
  247. int main()
  248. {
  249.     // идентификаторы потоков
  250.     pthread_t ad,dv,sb,sq;
  251.     // получаем очередь сообщений
  252.     msqid = msgget(IPC_PRIVATE, MSGPERM|IPC_CREAT|IPC_EXCL);
  253.     // создаем служебные потоки
  254.     pthread_create(&ad,0,&addThread,NULL);
  255.     pthread_create(&sb,0,&subThread,NULL);
  256.     pthread_create(&dv,0,&divThread,NULL);
  257.     pthread_create(&sq,0,&sqrThread,NULL);
  258.     // переменные с входными значениями
  259.     int first,second,third;
  260.     // вводим исходные данные
  261.     cout << "[Main]: First number: ";
  262.     cin >> first;
  263.     cout << "[Main]: Second number:";
  264.     cin >> second;
  265.     cout << "[Main]: Third number: ";
  266.     cin >> third;
  267.     // вычисляем дисперсию выборки из трех чисел
  268.     double t = mydiv(myadd(first,myadd(second,third)),3);
  269.     double res = mydiv(myadd(mysqr(mysub(first,t)),
  270.         myadd(mysqr(mysub(second,t)),mysqr(mysub(third,t)))),3);
  271.     // выводим полученный результат
  272.     cout << "[Main]: result: " << res << endl;
  273.     // блокируем мьютекс
  274.     pthread_mutex_lock(&mt);
  275.     // устанавливаем операцию выхода
  276.     cop = OP_EXIT;
  277.     // будим поток сложения
  278.     pthread_cond_signal(&addCond);
  279.     // разблокируем мьютекс
  280.     pthread_mutex_unlock(&mt);
  281.     // ждем, пока поток завершится
  282.     pthread_join(ad,NULL);
  283.     // аналогично, но с вычитанием
  284.     pthread_mutex_lock(&mt);
  285.     pthread_cond_signal(&subCond);
  286.     pthread_mutex_unlock(&mt);
  287.     pthread_join(sb,NULL);
  288.     // с делением
  289.     pthread_mutex_lock(&mt);
  290.     cop = OP_EXIT;
  291.     pthread_cond_signal(&divCond);
  292.     pthread_mutex_unlock(&mt);
  293.     pthread_join(dv,NULL);
  294.     // с квадратом
  295.     pthread_mutex_lock(&mt);
  296.     cop = OP_EXIT;
  297.     pthread_cond_signal(&sqrCond);
  298.     pthread_mutex_unlock(&mt);
  299.     pthread_join(sq,NULL);
  300.     // удаляем очередь
  301.     msgctl(msqid,IPC_RMID,NULL);
  302.     // выходим
  303.     return 0;
  304. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement