Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <pthread.h>
- #include <stdlib.h>
- #include <unistd.h>
- // несколько потоков
- // переменные состояния для синхронизации
- // очереди сообщений для обмена инфой
- // вычисляем дисперсию
- using namespace std;
- #define MSGPERM 0600
- // переменные состояния
- pthread_cond_t addCond = PTHREAD_COND_INITIALIZER,
- subCond = PTHREAD_COND_INITIALIZER,
- sqrCond = PTHREAD_COND_INITIALIZER,
- divCond = PTHREAD_COND_INITIALIZER,
- eEnd = PTHREAD_COND_INITIALIZER;
- // мьютекс для переменных состояния
- pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
- // специальная переменная, описывающая, что сейчас надо делать
- enum {OP_NONE,OP_ADD, OP_EXIT, OP_SUB, OP_SQR, OP_DIV} cop = OP_NONE;
- // идентификатор очереди сообщений
- int msqid;
- // структура сообщения
- typedef struct{
- public:
- long mtype;
- double a;
- double b;
- } mymsgbuf;
- // поток сложения
- void* addThread(void* arg)
- {
- // буфер для хранения сообщения
- mymsgbuf buf;
- // вечный цикл
- while(true)
- {
- // блокируем мьютекс
- pthread_mutex_lock(&mt);
- // и начинаем ждать сигнала и одного из двух значений переменной cop
- while((cop != OP_ADD)&&(cop != OP_EXIT))
- pthread_cond_wait(&addCond, &mt);
- // разблокируем мьютекс
- pthread_mutex_unlock(&mt);
- // если нужно выходить, то идём к выходу
- if(cop == OP_EXIT)
- break;
- // принимаем сообщение
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- // выводим лог
- cout << "[Adder]: " << buf.a << '+' << buf.b << endl;
- // осуществляем сложение
- buf.a = buf.a + buf.b;
- // отсылаем результат
- msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- // блокируем мьютекс
- pthread_mutex_lock(&mt);
- // переменную cop в состояние "ничегонеделания"
- cop = OP_NONE;
- // будим основной поток
- pthread_cond_signal(&eEnd);
- // разблокируем мьютекс
- pthread_mutex_unlock(&mt);
- }
- // выход из потока
- pthread_exit(0);
- }
- // всё также, как и выше, но с вычитанием
- void* subThread(void* arg)
- {
- mymsgbuf buf;
- while(true)
- {
- pthread_mutex_lock(&mt);
- while((cop != OP_SUB)&&(cop != OP_EXIT))
- pthread_cond_wait(&subCond, &mt);
- pthread_mutex_unlock(&mt);
- if(cop == OP_EXIT)
- break;
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- cout << "[Subtractor]: " << buf.a << '-' << buf.b << endl;
- buf.a = buf.a - buf.b;
- msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_NONE;
- pthread_cond_signal(&eEnd);
- pthread_mutex_unlock(&mt);
- }
- cout << "OK2" << endl;
- pthread_exit(0);
- }
- // аналогично, но с делением
- void* divThread(void* arg)
- {
- mymsgbuf buf;
- while(true)
- {
- pthread_mutex_lock(&mt);
- while((cop != OP_DIV)&&(cop != OP_EXIT))
- pthread_cond_wait(&divCond, &mt);
- pthread_mutex_unlock(&mt);
- if(cop == OP_EXIT)
- break;
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- cout << "[Divider]: " << buf.a << '/' << buf.b << endl;
- buf.a = buf.a / buf.b;
- msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_NONE;
- pthread_cond_signal(&eEnd);
- pthread_mutex_unlock(&mt);
- }
- cout << "OK2" << endl;
- pthread_exit(0);
- }
- // аналогично, но с возведением в квадрат
- void* sqrThread(void* arg)
- {
- mymsgbuf buf;
- while(true)
- {
- pthread_mutex_lock(&mt);
- while((cop != OP_SQR)&&(cop != OP_EXIT))
- pthread_cond_wait(&sqrCond, &mt);
- pthread_mutex_unlock(&mt);
- if(cop == OP_EXIT)
- break;
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- cout << "[Squarer]: " << buf.a << "^2" << endl;
- buf.a = buf.a * buf.a;
- msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_NONE;
- pthread_cond_signal(&eEnd);
- pthread_mutex_unlock(&mt);
- }
- cout << "OK2" << endl;
- pthread_exit(0);
- }
- // процедура для взаимодействия с потоком сложения
- double myadd(double a, double b)
- {
- // буфер для хранения сообщения
- mymsgbuf buf;
- // инициализируем буфер нужными значениями
- buf.a = a;
- buf.b = b;
- buf.mtype = 1;
- // отсылаем сообщение
- rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- // блокирвем мьютекс
- pthread_mutex_lock(&mt);
- // устанавливаем действие "сложение"
- cop = OP_ADD;
- // будим слагательный поток
- pthread_cond_signal(&addCond);
- // разблокируем мьютекс
- pthread_mutex_unlock(&mt);
- // снова блокируем
- pthread_mutex_lock(&mt);
- // ждём, пока операция не выполнится
- while(cop != OP_NONE)
- pthread_cond_wait(&eEnd, &mt);
- // разблокируем
- pthread_mutex_unlock(&mt);
- // принимаем ответ
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- // выдаем ответ
- return buf.a;
- }
- // аналогично, как выше, но с вычитанием
- double mysub(double a, double b)
- {
- mymsgbuf buf;
- buf.a = a;
- buf.b = b;
- buf.mtype = 1;
- rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_SUB;
- pthread_cond_signal(&subCond);
- pthread_mutex_unlock(&mt);
- pthread_mutex_lock(&mt);
- while(cop != OP_NONE)
- pthread_cond_wait(&eEnd, &mt);
- pthread_mutex_unlock(&mt);
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- return buf.a;
- }
- // аналогично, но с делением
- double mydiv(double a, double b)
- {
- mymsgbuf buf;
- buf.a = a;
- buf.b = b;
- buf.mtype = 1;
- rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_DIV;
- pthread_cond_signal(&divCond);
- pthread_mutex_unlock(&mt);
- pthread_mutex_lock(&mt);
- while(cop != OP_NONE)
- pthread_cond_wait(&eEnd, &mt);
- pthread_mutex_unlock(&mt);
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- return buf.a;
- }
- // аналогично, но с возведением в квадрат
- double mysqr(double a)
- {
- mymsgbuf buf;
- buf.a = a;
- buf.mtype = 1;
- rc = msgsnd(msqid,&buf,sizeof(mymsgbuf),0);
- pthread_mutex_lock(&mt);
- cop = OP_SQR;
- pthread_cond_signal(&sqrCond);
- pthread_mutex_unlock(&mt);
- pthread_mutex_lock(&mt);
- while(cop != OP_NONE)
- pthread_cond_wait(&eEnd, &mt);
- pthread_mutex_unlock(&mt);
- msgrcv(msqid,&buf,sizeof(mymsgbuf),0,0);
- return buf.a;
- }
- int main()
- {
- // идентификаторы потоков
- pthread_t ad,dv,sb,sq;
- // получаем очередь сообщений
- msqid = msgget(IPC_PRIVATE, MSGPERM|IPC_CREAT|IPC_EXCL);
- // создаем служебные потоки
- pthread_create(&ad,0,&addThread,NULL);
- pthread_create(&sb,0,&subThread,NULL);
- pthread_create(&dv,0,&divThread,NULL);
- pthread_create(&sq,0,&sqrThread,NULL);
- // переменные с входными значениями
- int first,second,third;
- // вводим исходные данные
- cout << "[Main]: First number: ";
- cin >> first;
- cout << "[Main]: Second number:";
- cin >> second;
- cout << "[Main]: Third number: ";
- cin >> third;
- // вычисляем дисперсию выборки из трех чисел
- double t = mydiv(myadd(first,myadd(second,third)),3);
- double res = mydiv(myadd(mysqr(mysub(first,t)),
- myadd(mysqr(mysub(second,t)),mysqr(mysub(third,t)))),3);
- // выводим полученный результат
- cout << "[Main]: result: " << res << endl;
- // блокируем мьютекс
- pthread_mutex_lock(&mt);
- // устанавливаем операцию выхода
- cop = OP_EXIT;
- // будим поток сложения
- pthread_cond_signal(&addCond);
- // разблокируем мьютекс
- pthread_mutex_unlock(&mt);
- // ждем, пока поток завершится
- pthread_join(ad,NULL);
- // аналогично, но с вычитанием
- pthread_mutex_lock(&mt);
- pthread_cond_signal(&subCond);
- pthread_mutex_unlock(&mt);
- pthread_join(sb,NULL);
- // с делением
- pthread_mutex_lock(&mt);
- cop = OP_EXIT;
- pthread_cond_signal(&divCond);
- pthread_mutex_unlock(&mt);
- pthread_join(dv,NULL);
- // с квадратом
- pthread_mutex_lock(&mt);
- cop = OP_EXIT;
- pthread_cond_signal(&sqrCond);
- pthread_mutex_unlock(&mt);
- pthread_join(sq,NULL);
- // удаляем очередь
- msgctl(msqid,IPC_RMID,NULL);
- // выходим
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement