Загрузка данных


#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;
}