← index
cplusplus2x.Examples/C++20/concurrency/sem.cpp
Source: cplusplus2x.Examples/C++20/concurrency/sem.cpp
// Help for this from: C++20 The Complete Guide
// Chapter 17.2 "Semaphores"

#include <chrono>
#include <iostream>
#include <mutex>
#include <queue>
#include <semaphore>
#include <thread>

int main() {
    std::queue<char> val;
    std::mutex val_mut;
    for (int i = 0; i < 5000; ++i) {
        val.push('a' + (i % ('z' - 'a')));
    }
    constexpr int thread_count = 10;
    std::counting_semaphore<thread_count> enabled{0};
    std::vector<std::jthread> pool;
    for (int i = 0; i < thread_count; ++i) {
        pool.push_back(std::jthread{[&enabled, &val, &val_mut, i](std::stop_token st) {
            auto id = std::this_thread::get_id();

            while (!st.stop_requested()) {
                enabled.acquire();
                char v;
                {
                    std::lock_guard lockg{val_mut};
                    v = val.front();
                    val.pop();
                }
                for (int j = 0; j < 10; ++j) {
                    std::cout << "thread id: " << id << " " << v << "\n";
                    auto dur = std::chrono::milliseconds(130) * ((i % 3) + 1);
                    std::this_thread::sleep_for(dur);
                }
                enabled.release();
            }
        }});
    }
    std::cout << "wait 2 seconds " << std::flush;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "enable 3 parallel threads..\n";
    enabled.release(3);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "enable 2 more\n"
              << std::flush;
    enabled.release(2);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    for (auto &tobj : pool) {
        tobj.request_stop();
    }
    return 0;
}