Untitled
unknown
plain_text
9 months ago
4.4 kB
4
Indexable
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <ncurses.h>
#include <unistd.h>
#include <condition_variable>
using namespace std;
// Liczba filozofów
int NUM_PHILOSOPHERS;
// Mutex chroniący dostęp do stołu
mutex table_mutex;
// Wektory przechowujące mutexy dla widelców
vector<unique_ptr<mutex>> forks;
// Mutex do synchronizacji wyjścia NCurses
mutex output_mtx;
// Licznik liczby posiłków dla każdego filozofa
vector<int> eating_count;
// Wektor przechowujący informację, czy filozof może jeść
vector<bool> can_eat;
// Stany filozofów: MYŚLENIE lub JEDZENIE
enum State { THINKING, EATING };
vector<State> philosopher_state;
// Mutex i zmienna warunkowa do synchronizacji kelnera
std::mutex waiter_mutex;
std::condition_variable waiter_cv;
int eating_philosophers = 0;
// Konwersja stanu filozofa na string
string state_to_string(State state) {
return state == THINKING ? "MYSLI" : "JE";
}
// Funkcja wyświetlająca aktualny stan filozofów w terminalu
void printStatus() {
lock_guard<mutex> lock(output_mtx); // Zabezpieczenie przed równoczesnym dostępem do ekranu
lock_guard<mutex> table_lock(table_mutex); // Zabezpieczenie przed równoczesnym odczytem danych
clear(); // Czyszczenie ekranu ncurses
mvprintw(0, 0, "FILOZOF:"); // Nagłówek kolumny z numerami filozofów
mvprintw(0, 10, "STAN:"); // Nagłówek kolumny ze stanami filozofów
mvprintw(0, 40, "LICZNIK NAJEDZENIA:"); // Nagłówek kolumny z licznikami posiłków
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
mvprintw(i + 1, 0, "%d.", i + 1); // Wyświetlenie numeru filozofa
mvprintw(i + 1, 10, "%s", state_to_string(philosopher_state[i]).c_str()); // Wyświetlenie aktualnego stanu filozofa
mvprintw(i + 1, 40, "%d", eating_count[i]); // Wyświetlenie licznika liczby posiłków
}
refresh(); // Odświeżenie ekranu ncurses, aby zmiany były widoczne
}
// Funkcja zmieniająca stan filozofa z zachowaniem synchronizacji
void change_state(int id, State state) {
lock_guard<mutex> lock(table_mutex);
philosopher_state[id] = state;
}
// Funkcja symulująca zachowanie filozofa
void philosopher(int id) {
while (eating_count[id] < 100) { // Filozof działa, dopóki nie zje 100 razy
change_state(id, THINKING);
printStatus();
this_thread::sleep_for(chrono::milliseconds(rand() % 1000 + 500));
unique_lock<mutex> waiter_lock(waiter_mutex);
waiter_cv.wait(waiter_lock, [id] {
return !can_eat[(id + NUM_PHILOSOPHERS - 1) % NUM_PHILOSOPHERS] &&
!can_eat[(id + 1) % NUM_PHILOSOPHERS];
});
eating_philosophers++;
can_eat[id] = true;
waiter_lock.unlock();
// Podnoszenie widelcow
lock_guard<mutex> left_fork_lock(*forks[id]);
lock_guard<mutex> right_fork_lock(*forks[(id + 1) % NUM_PHILOSOPHERS]);
change_state(id, EATING);
eating_count[id]++;
printStatus();
this_thread::sleep_for(chrono::milliseconds(rand() % 1000 + 500));
waiter_lock.lock();
eating_philosophers--;
can_eat[id] = false;
waiter_cv.notify_all();
}
}
void display()
{
while(true)
{
printStatus();
usleep(250000);
}
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <number_of_philosophers>" << endl;
return 1;
}
NUM_PHILOSOPHERS = stoi(argv[1]);
if (NUM_PHILOSOPHERS < 2) {
cerr << "Number of philosophers must be at least 2." << endl;
return 1;
}
forks.resize(NUM_PHILOSOPHERS);
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
forks[i] = make_unique<mutex>();
}
eating_count.resize(NUM_PHILOSOPHERS, 0);
philosopher_state.resize(NUM_PHILOSOPHERS, THINKING);
can_eat.resize(NUM_PHILOSOPHERS, false);
initscr();
noecho();
curs_set(FALSE);
vector<thread> philosophers;
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
philosophers.push_back(thread(philosopher, i));
}
thread display_thread(display);
for (auto& p : philosophers) {
p.join();
}
display_thread.join();
endwin();
getch(); // Oczekiwanie na naciśnięcie klawisza przed zamknięciem programu
return 0;
}Editor is loading...
Leave a Comment