//----------------------------------------------- // common.h //----------------------------------------------- #ifndef common_h #define common_h //--------------------------------------------- #include // std::chrono::milliseconds #include // std::size_t #include // std::stoul, EXIT_SUCCESS #include // getopt, optarg #include // std::cout, std::endl #include // std::jthread, std::this_thread::sleep_for #include // std::tuple #include // std::vector //----------------------------------------------- using namespace std::literals; //----------------------------------------------- std::tuple parser(int argc, char *argv[]) { std::chrono::milliseconds runtime = 10ms; std::size_t threads = 8; int option = 0; while ((option = getopt(argc, argv, "r:t:h")) != -1) switch (option) { case 'r': runtime = std::chrono::milliseconds(std::stoul(optarg)); break; case 't': threads = std::stoul(optarg); break; default: std::cout << argv[0] << " options:\n" << "\t-r: runtime in milliseconds, default: " << runtime.count() << "ms\n" << "\t-t: number of reader and writer threads, min: " "1, max: 10, " "default: " << threads << "\n" << "\t-h: show this help\n"; exit(EXIT_SUCCESS); break; } return {runtime, std::min(10uz, std::max(1uz, threads))}; } //----------------------------------------------- void critical_section(char c) { for (char i = 0; i < 10; ++i) std::cout << c; std::cout << '\n'; } //----------------------------------------------- template void reader(std::stop_token stop, lock_t &lock, char c) { while (!stop.stop_requested()) { lock.reader_lock(); // importante!!! if (!stop.stop_requested()) critical_section(c); lock.reader_unlock(); // importante!!! } } //----------------------------------------------- template void writer(std::stop_token stop, lock_t &lock, char c) { while (!stop.stop_requested()) { lock.writer_lock(); // importante!!! if (!stop.stop_requested()) critical_section(c); lock.writer_unlock(); // importante!!! } } //----------------------------------------------- template int common_main(int argc, char *argv[]) { auto [runtime, threads] = parser(argc, argv); lock_t lock(threads); std::vector workers; workers.reserve(threads); for (std::size_t i = 0; i < threads; ++i) { workers.emplace_back(reader, std::ref(lock), '0' + i); workers.emplace_back(writer, std::ref(lock), 'a' + i); } std::this_thread::sleep_for(runtime); for (auto &worker : workers) worker.request_stop(); std::cout << std::flush; return EXIT_SUCCESS; } //----------------------------------------------- #endif // common_h