| 29 | } |
| 30 | |
| 31 | class alignas(128 /*std::hardware_destructive_interference_size*/) Guide { |
| 32 | inline static co_context::mutex cout_mutex; |
| 33 | inline static std::chrono::time_point<std::chrono::high_resolution_clock> |
| 34 | started_at; |
| 35 | unsigned delay{rnd()}, occupy{rnd()}, wait_on_sema{}; |
| 36 | |
| 37 | public: |
| 38 | static void start_time() { |
| 39 | started_at = std::chrono::high_resolution_clock::now(); |
| 40 | } |
| 41 | |
| 42 | task<void> initial_delay() const { co_await timeout(delay * time_tick); } |
| 43 | |
| 44 | task<void> occupy_sema() { |
| 45 | wait_on_sema = static_cast<unsigned>( |
| 46 | std::chrono::duration_cast<std::chrono::milliseconds>( |
| 47 | std::chrono::high_resolution_clock::now() - started_at |
| 48 | - delay * time_tick |
| 49 | ) |
| 50 | .count() |
| 51 | / time_tick.count() |
| 52 | ); |
| 53 | co_await timeout(occupy * time_tick); |
| 54 | } |
| 55 | |
| 56 | task<void> visualize(unsigned id, unsigned x_scale = 2) const { |
| 57 | auto cout_n = [=](auto str, unsigned n) { |
| 58 | n *= x_scale; |
| 59 | while (n-- > 0) { |
| 60 | std::cout << str; |
| 61 | } |
| 62 | }; |
| 63 | auto guard = co_await cout_mutex.lock_guard(); |
| 64 | std::cout << "#" << std::setw(2) << id << " "; |
| 65 | cout_n("░", delay); |
| 66 | cout_n("▒", wait_on_sema); |
| 67 | cout_n("█", occupy); |
| 68 | std::cout << '\n'; |
| 69 | } |
| 70 | |
| 71 | static void show_info() { |
| 72 | std::cout |
| 73 | << "\nThreads: " << max_threads |
| 74 | << ", Throughput: " << max_sema_threads |
| 75 | << " │ Legend: initial delay ░░ │ wait state ▒▒ │ sema occupation ██ \n" |
| 76 | << std::endl; |
| 77 | } |
| 78 | }; |
| 79 | |
| 80 | std::array<Guide, max_threads> guides; |
| 81 | |