Загрузка данных
#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
const int NUM_SHIPS = 2;
const int SHIP_CAPACITY = 5;
const int NUM_PILGRIMS = 20;
const int MIN_SAIL_TIME = 8000;
const int MAX_SAIL_TIME = 15000;
const int MIN_ARRIVAL_DELAY = 200;
const int MAX_ARRIVAL_DELAY = 800;
const int MIN_PATIENCE = 1000;
const int MAX_PATIENCE = 3000;
HANDLE gMutex;
HANDLE gFinishEvent;
int gTotalPilgrims = 0;
int gByShip = 0;
int gOnFoot = 0;
struct Ship
{
int id;
int passengers;
bool inPort;
HANDLE fullEvent;
};
Ship gShips[NUM_SHIPS];
struct PilgrimData
{
int id;
int patienceMs;
};
int RandomRange(int left, int right)
{
return left + rand() % (right - left + 1);
}
void SafePrint(const string& text)
{
WaitForSingleObject(gMutex, INFINITE);
cout << text << endl;
ReleaseMutex(gMutex);
}
DWORD WINAPI ShipThread(LPVOID lpParam)
{
Ship* ship = (Ship*)lpParam;
HANDLE waitHandles[2];
waitHandles[0] = ship->fullEvent;
waitHandles[1] = gFinishEvent;
while (true)
{
WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
if (WaitForSingleObject(gFinishEvent, 0) == WAIT_OBJECT_0)
{
SafePrint("Корабль #" + to_string(ship->id) + " завершает работу.");
return 0;
}
WaitForSingleObject(gMutex, INFINITE);
ship->inPort = false;
cout << "Корабль #" << ship->id
<< " заполнен (" << ship->passengers
<< " паломников) и отплывает." << endl;
ReleaseMutex(gMutex);
int sailTime = RandomRange(MIN_SAIL_TIME, MAX_SAIL_TIME);
Sleep(sailTime);
WaitForSingleObject(gMutex, INFINITE);
cout << "Корабль #" << ship->id
<< " вернулся из плавания." << endl;
ship->passengers = 0;
ship->inPort = true;
ResetEvent(ship->fullEvent);
ReleaseMutex(gMutex);
}
}
DWORD WINAPI PilgrimThread(LPVOID lpParam)
{
PilgrimData* pilgrim = (PilgrimData*)lpParam;
DWORD startTime = GetTickCount();
WaitForSingleObject(gMutex, INFINITE);
cout << "Паломник #" << pilgrim->id
<< " пришел в порт. Терпение: "
<< pilgrim->patienceMs << " мс." << endl;
ReleaseMutex(gMutex);
while (true)
{
bool boarded = false;
WaitForSingleObject(gMutex, INFINITE);
for (int i = 0; i < NUM_SHIPS; i++)
{
if (gShips[i].inPort && gShips[i].passengers < SHIP_CAPACITY)
{
gShips[i].passengers++;
int placeNumber = gShips[i].passengers;
cout << "Паломник #" << pilgrim->id
<< " сел на корабль #" << gShips[i].id
<< ". Место " << placeNumber
<< "/" << SHIP_CAPACITY << "." << endl;
gByShip++;
boarded = true;
if (gShips[i].passengers == SHIP_CAPACITY)
{
SetEvent(gShips[i].fullEvent);
}
break;
}
}
ReleaseMutex(gMutex);
if (boarded)
{
delete pilgrim;
return 0;
}
DWORD now = GetTickCount();
DWORD waited = now - startTime;
if (waited >= (DWORD)pilgrim->patienceMs)
{
WaitForSingleObject(gMutex, INFINITE);
cout << "Паломник #" << pilgrim->id
<< " устал ждать и ушел пешком." << endl;
gOnFoot++;
ReleaseMutex(gMutex);
delete pilgrim;
return 0;
}
Sleep(100);
}
}
int main()
{
setlocale(LC_ALL, "Russian");
srand((unsigned int)time(nullptr));
gTotalPilgrims = NUM_PILGRIMS;
gMutex = CreateMutex(NULL, FALSE, NULL);
if (gMutex == NULL)
{
cout << "Ошибка создания mutex. Код: " << GetLastError() << endl;
return 1;
}
gFinishEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (gFinishEvent == NULL)
{
cout << "Ошибка создания события завершения. Код: " << GetLastError() << endl;
CloseHandle(gMutex);
return 1;
}
for (int i = 0; i < NUM_SHIPS; i++)
{
gShips[i].id = i + 1;
gShips[i].passengers = 0;
gShips[i].inPort = true;
gShips[i].fullEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (gShips[i].fullEvent == NULL)
{
cout << "Ошибка создания события корабля. Код: " << GetLastError() << endl;
for (int j = 0; j < i; j++)
{
CloseHandle(gShips[j].fullEvent);
}
CloseHandle(gFinishEvent);
CloseHandle(gMutex);
return 1;
}
}
HANDLE shipThreads[NUM_SHIPS];
for (int i = 0; i < NUM_SHIPS; i++)
{
shipThreads[i] = CreateThread(NULL, 0, ShipThread, &gShips[i], 0, NULL);
if (shipThreads[i] == NULL)
{
cout << "Ошибка создания потока корабля. Код: " << GetLastError() << endl;
SetEvent(gFinishEvent);
for (int j = 0; j < i; j++)
{
CloseHandle(shipThreads[j]);
}
for (int j = 0; j < NUM_SHIPS; j++)
{
CloseHandle(gShips[j].fullEvent);
}
CloseHandle(gFinishEvent);
CloseHandle(gMutex);
return 1;
}
}
vector<HANDLE> pilgrimThreads;
for (int i = 0; i < NUM_PILGRIMS; i++)
{
PilgrimData* data = new PilgrimData;
data->id = i + 1;
data->patienceMs = RandomRange(MIN_PATIENCE, MAX_PATIENCE);
HANDLE hPilgrim = CreateThread(NULL, 0, PilgrimThread, data, 0, NULL);
if (hPilgrim == NULL)
{
cout << "Ошибка создания потока паломника. Код: " << GetLastError() << endl;
delete data;
continue;
}
pilgrimThreads.push_back(hPilgrim);
Sleep(RandomRange(MIN_ARRIVAL_DELAY, MAX_ARRIVAL_DELAY));
}
if (!pilgrimThreads.empty())
{
WaitForMultipleObjects((DWORD)pilgrimThreads.size(), pilgrimThreads.data(), TRUE, INFINITE);
}
SafePrint("Все паломники завершили выбор способа перемещения.");
SetEvent(gFinishEvent);
for (int i = 0; i < NUM_SHIPS; i++)
{
SetEvent(gShips[i].fullEvent);
}
WaitForMultipleObjects(NUM_SHIPS, shipThreads, TRUE, INFINITE);
cout << "\n========== ИТОГ ==========" << endl;
cout << "Всего паломников: " << gTotalPilgrims << endl;
cout << "Добрались на кораблях: " << gByShip << endl;
cout << "Ушли пешком: " << gOnFoot << endl;
cout << "==========================\n" << endl;
for (HANDLE h : pilgrimThreads)
{
CloseHandle(h);
}
for (int i = 0; i < NUM_SHIPS; i++)
{
CloseHandle(shipThreads[i]);
CloseHandle(gShips[i].fullEvent);
}
CloseHandle(gFinishEvent);
CloseHandle(gMutex);
return 0;
}