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


#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <iomanip>

using namespace std;

const int NUM_THREADS = 3;

struct ProcessInfo {
    int id;
    int burst_time;
    int remaining_time;
    int arrival_time;
    int counter;
    int finish_time;
    int waiting_time;
    int turnaround_time;
};

mutex mtx;
condition_variable cv_scheduler;
condition_variable cv_worker[NUM_THREADS];

bool run_token[NUM_THREADS] = { false };
bool worker_finished_step = false;
bool stop_all = false;
int current_time = 0;

ProcessInfo processes[NUM_THREADS] = {
    {0, 6, 6, 0, 0, 0, 0, 0},
    {1, 2, 2, 2, 0, 0, 0, 0},
    {2, 4, 4, 5, 0, 0, 0, 0}
};

void worker_thread(int id) {
    while (true) {
        unique_lock<mutex> lock(mtx);

        cv_worker[id].wait(lock, [&]() {
            return run_token[id] || stop_all;
        });

        if (stop_all) break;

        processes[id].counter += 10;
        processes[id].remaining_time--;
        current_time++;

        cout << "  [t = " << setw(2) << current_time << "]  |   Поток P" << id
             << "   |  Счётчик: " << setw(3) << processes[id].counter
             << "  |  Осталось тиков: " << setw(2) << processes[id].remaining_time << "\n";

        if (processes[id].remaining_time == 0) {
            processes[id].finish_time = current_time;
        }

        run_token[id] = false;
        worker_finished_step = true;
        cv_scheduler.notify_one();

        lock.unlock();
        this_thread::sleep_for(chrono::milliseconds(100));
    }
}

int main() {
    setlocale(LC_ALL, "Russian");

    cout << "+-----------------------------------------------------------------------+\n";
    cout << "|         МОДЕЛИРОВАНИЕ АЛГОРИТМА SJF (SRTF - ВЫТЕСНЯЮЩИЙ)              |\n";
    cout << "|                     Количество потоков: 3                             |\n";
    cout << "+-----------------------------------------------------------------------+\n\n";

    cout << "ВХОДНЫЕ ДАННЫЕ ПРОЦЕССОВ:\n";
    cout << "+---------+----------------------+---------------------+\n";
    cout << "| Процесс | Время прихода (Тприх)| Время работы (Тисп) |\n";
    cout << "+---------+----------------------+---------------------+\n";
    for (int i = 0; i < NUM_THREADS; ++i) {
        cout << "|   P" << processes[i].id << "    |          " 
             << setw(2) << processes[i].arrival_time << "          |         " 
             << setw(2) << processes[i].burst_time << "          |\n";
    }
    cout << "+---------+----------------------+---------------------+\n\n";

    cout << "ХОД ВЫПОЛНЕНИЯ:\n";
    cout << "-------------------------------------------------------------------------\n";

    vector<thread> threads;
    for (int i = 0; i < NUM_THREADS; ++i) {
        threads.emplace_back(worker_thread, i);
    }

    int total_remaining = 0;
    for (int i = 0; i < NUM_THREADS; ++i) {
        total_remaining += processes[i].burst_time;
    }

    int last_running_id = -1;

    while (total_remaining > 0) {
        int best_id = -1;
        int min_rem = 1e9;

        for (int i = 0; i < NUM_THREADS; ++i) {
            if (processes[i].arrival_time <= current_time && processes[i].remaining_time > 0) {
                if (processes[i].remaining_time < min_rem) {
                    min_rem = processes[i].remaining_time;
                    best_id = i;
                }
            }
        }

        if (best_id != last_running_id) {
            if (last_running_id != -1 && processes[last_running_id].remaining_time > 0) {
                cout << "\n  >>> [t = " << current_time << "] [ВЫТЕСНЕНИЕ] Поток P" 
                     << last_running_id << " вытеснен потоком P" << best_id 
                     << " (остаток времени меньше) <<<\n\n";
            } else {
                cout << "\n  >>> [t = " << current_time << "] Переключение ЦП на поток P" 
                     << best_id << " <<<\n\n";
            }
            last_running_id = best_id;
        }

        {
            unique_lock<mutex> lock(mtx);
            worker_finished_step = false;
            run_token[best_id] = true;
            cv_worker[best_id].notify_one();
        }

        {
            unique_lock<mutex> lock(mtx);
            cv_scheduler.wait(lock, []() { return worker_finished_step; });
        }

        total_remaining--;

        if (processes[best_id].remaining_time == 0) {
            cout << "  >>> Поток P" << best_id << " ПОЛНОСТЬЮ ЗАВЕРШЁН в t = " 
                 << processes[best_id].finish_time << " <<<\n";
        }
    }

    {
        unique_lock<mutex> lock(mtx);
        stop_all = true;
        for (int i = 0; i < NUM_THREADS; ++i) {
            cv_worker[i].notify_one();
        }
    }

    for (auto& th : threads) {
        if (th.joinable()) {
            th.join();
        }
    }

    double avg_waiting = 0;
    double avg_turnaround = 0;

    cout << "\n-------------------------------------------------------------------------\n";
    cout << "ИТОГОВЫЕ РЕЗУЛЬТАТЫ ПЛАНИРОВАНИЯ:\n";
    cout << "+---------+----------+----------+----------+-----------------+------------------+\n";
    cout << "| Процесс |  Тприх   |   Тисп   |   Ткон   | Полное (Тполн)  | Ожидание (Тож)   |\n";
    cout << "+---------+----------+----------+----------+-----------------+------------------+\n";

    for (int i = 0; i < NUM_THREADS; ++i) {
        processes[i].turnaround_time = processes[i].finish_time - processes[i].arrival_time;
        processes[i].waiting_time = processes[i].turnaround_time - processes[i].burst_time;

        avg_waiting += processes[i].waiting_time;
        avg_turnaround += processes[i].turnaround_time;

        cout << "|   P" << processes[i].id << "    |    "
             << setw(2) << processes[i].arrival_time << "    |    "
             << setw(2) << processes[i].burst_time << "    |    "
             << setw(2) << processes[i].finish_time << "    |       "
             << setw(2) << processes[i].turnaround_time << "        |        "
             << setw(2) << processes[i].waiting_time << "        |\n";
    }

    avg_waiting /= NUM_THREADS;
    avg_turnaround /= NUM_THREADS;

    cout << "+---------+----------+----------+----------+-----------------+------------------+\n";
    cout << "| СРЕДНИЕ ЗНАЧЕНИЯ:                            |      " 
         << fixed << setprecision(2) << setw(5) << avg_turnaround << "      |      " 
         << fixed << setprecision(2) << setw(5) << avg_waiting << "       |\n";
    cout << "+----------------------------------------------+-----------------+------------------+\n";

    cout << "\nНажмите клавишу Enter для выхода из программы...";
    cin.get();

    return 0;
}