Тема: мережі Петрі, багатопотокове обчислення прикладу
Завдання. За допомогою мережі Петрі виконати (багатопотокове) обчислення прикладу Zn = SIN( Un + COS( Vn ) ) * COS( SIN( Un + Vn ) )
Кому лінь читати статтю про мережі Петрі, дивіться короткі пояснення
коло - це Вузол
рисочка або чотирикутник - Стан
Якщо вузол маркований (має 1 або більше крапку в колі) то можна здійснювати перехід на ін. вузол.
Стан перевіряє чи всі вузли марковані, якщо це так то здійсниться перехід.
Але є багато чого іншого, наприклад заперечення, вага дуг та інше.
#include <iostream>
#include <Windows.h>
#include <process.h>
#include <cmath>
/*
Zn = SIN( Un + COS( Vn ) ) * COS( SIN( Un + Vn ) )
*/
namespace example
{
struct sMathOperation
{
sMathOperation() = default;
sMathOperation(void *par);
double a;
double b;
double result;
};
sMathOperation::sMathOperation(void *par)
{
sMathOperation *obj = reinterpret_cast<sMathOperation*>(par);
this->a = obj->a;
this->b = obj->b;
this->result = obj->result;
}
struct sMathFunction
{
sMathFunction() = default;
sMathFunction(void *par);
double (*mathFunction)(double);
double a;
double result;
};
sMathFunction::sMathFunction(void *par)
{
sMathFunction *obj = reinterpret_cast<sMathFunction*>(par);
this->mathFunction = obj->mathFunction;
this->a = obj->a;
this->result = obj->result;
}
class example
{
public:
example(double Un_, double Vn_);
double getResult();
private:
static void add(void *par);
static void multiply(void *par);
static void mathFunction(void *par);
double Un;
double Vn;
double result;
};
example::example(double Un_, double Vn_) : Un(Un_), Vn(Vn_)
{
//array
HANDLE hand[2];
//calculation example Un + Vn
sMathOperation *sAddOperation = new sMathOperation;
sAddOperation->a = Un;
sAddOperation->b = Vn;
hand[0] = (HANDLE)_beginthread(&example::add, 0, sAddOperation);
//calculation example COS( Vn )
sMathFunction *sCosFunction = new sMathFunction;
sCosFunction->a = Vn;
sCosFunction->mathFunction = cos;
hand[1] = (HANDLE)_beginthread(&example::mathFunction, 0, sCosFunction);
//wait previous operations
WaitForMultipleObjects(2, hand, true, INFINITE);
//calculation example SIN( Un + Vn )
sMathFunction *sSinFunction = new sMathFunction;
sSinFunction->a = sAddOperation->result;
sSinFunction->mathFunction = sin;
hand[0] = (HANDLE)_beginthread(&example::mathFunction, 0, sSinFunction);
//delete previous object
delete sAddOperation;
//calculation example Un + COS( Vn )
sAddOperation = new sMathOperation;
sAddOperation->a = Un;
sAddOperation->b = sCosFunction->result;
hand[1] = (HANDLE)_beginthread(&example::add, 0, sAddOperation);
//delete previous object
delete sCosFunction;
//wait previous operations
WaitForMultipleObjects(2, hand, true, INFINITE);
//calculation example COS( SIN( Un + Vn ) )
sCosFunction = new sMathFunction;
sCosFunction->a = sSinFunction->result;
sCosFunction->mathFunction = cos;
hand[0] = (HANDLE)_beginthread(&example::mathFunction, 0, sCosFunction);
//delete previous object
delete sSinFunction;
//calculation example SIN( Un + COS( Vn ) )
sSinFunction = new sMathFunction;
sSinFunction->a = sAddOperation->result;
sSinFunction->mathFunction = sin;
hand[1] = (HANDLE)_beginthread(&example::mathFunction, 0, sSinFunction);
//delete previous object
delete sAddOperation;
//wait previous operations
WaitForMultipleObjects(2, hand, true, INFINITE);
//calculation example SIN( Un + COS( Vn ) ) * COS( SIN( Un + Vn ) )
sMathOperation *sMultiplyOperation = new sMathOperation;
sMultiplyOperation->a = sCosFunction->result;
sMultiplyOperation->b = sSinFunction->result;
hand[0] = (HANDLE)_beginthread(&example::multiply, 0, sMultiplyOperation);
//delete previous objects
delete sCosFunction;
delete sSinFunction;
//wait previous operation
WaitForSingleObject(hand[0], INFINITE);
//result
result = sMultiplyOperation->result;
//delete previous object
delete sMultiplyOperation;
}
double example::getResult()
{
return result;
}
void example::add(void *par)
{
sMathOperation *obj = (sMathOperation *)par;
obj->result = obj->a + obj->b;
}
void example::multiply(void *par)
{
sMathOperation *obj = (sMathOperation *)par;
obj->result = obj->a * obj->b;
}
void example::mathFunction(void *par)
{
sMathFunction *obj = (sMathFunction *)par;
obj->result = obj->mathFunction(obj->a);
}
}
int main(int argc, char *argv[]) try
{
double Un,
Vn;
//get Un, Vn
std::cout << "Enter Un ->";
std::cin >> Un;
std::cout << "Enter Vn ->";
std::cin >> Vn;
//multi-threaded
example::example obj(Un, Vn);
//single-threaded
double Zn;
Zn = sin(Un + cos(Vn)) * cos(sin(Un + Vn));
//output results
std::cout << "(multi-threaded) Zn = " << obj.getResult() << std::endl;
std::cout << "(single-threaded) Zn = " << Zn << std::endl;
system("pause");
return 0;
}
catch (...)
{
std::cout << "\ncritical error!\n";
system("pause");
return -1;
}
В ролі "стану" виступають функції WaitForMultiplyObjects i WaitForSingleObject, вони чекають виконання попередніх дій тим самим не даючи запустити програмі нові потоки.
Я дивився як можна у функцію, що буде виконуватися новим потоком, передати декілька аргументів і знайшов пораду використовувати структури (struct), а в функцію передавати об'єкт структури
Ось і все, не знаю чи правильно я зробив (можливо це робиться якось простіше), але програма робити і показує правильний результат