#include <array>
#include <chrono>
#include <cstddef>
#include <iostream>
#include <random>
#include <semaphore>
#include <string>
#include <thread>
#include <vector>
 
struct Seat {
    bool is_occupied = false;
    std::string name;
};
 
constexpr int SEAT_NUM = 100;
std::array<Seat, SEAT_NUM> seats_table;
std::counting_semaphore<SEAT_NUM> avaliable_seats(SEAT_NUM);
std::binary_semaphore table_mutex(1);
 
void reader(int id) {
    auto name = "Reader_" + std::to_string(id);
    avaliable_seats.acquire();
    int seat_number = -1;
    table_mutex.acquire();
    for (size_t i = 0; i < seats_table.size(); i++) {
        if (not seats_table.at(i).is_occupied) {
            seats_table[i] = {.is_occupied = true, .name = name};
            seat_number = i;
            break;
        }
    }
    std::cout << name << " take seat at " << seat_number << std::endl;
    table_mutex.release();
    std::random_device rd;
    std::uniform_int_distribution uin(3,3000);
    std::this_thread::sleep_for(std::chrono::microseconds(uin(rd)));
    table_mutex.acquire();
    seats_table.at(seat_number).is_occupied=false;
    table_mutex.release();
    avaliable_seats.release();
}
 
int main() {
    constexpr int NUM_READERS = 200;
    std::vector<std::thread> readers;
 
    for (int i = 0; i < NUM_READERS; i++) {
        readers.emplace_back(reader, i);
    }
 
    for (auto& reader_thread : readers) {
        reader_thread.join();
    }
 
}
set(CMAKE_CXX_STANDARD 23)