1
0
Fork 0
mirror of https://gitlab.com/niansa/libcrosscoro.git synced 2025-03-06 20:53:32 +01:00
libcrosscoro/examples/coro_ring_buffer.cpp
Josh Baldwin c1acf8b80d
coro::semaphore (#65)
* coro::semaphore

* coro::ring_buffer<E, N>
2021-02-23 11:05:21 -07:00

72 lines
2.1 KiB
C++

#include <coro/coro.hpp>
#include <iostream>
int main()
{
const size_t iterations = 100;
const size_t consumers = 4;
coro::thread_pool tp{coro::thread_pool::options{.thread_count = 4}};
coro::ring_buffer<uint64_t, 16> rb{};
coro::mutex m{};
std::vector<coro::task<void>> tasks{};
auto make_producer_task = [&]() -> coro::task<void> {
co_await tp.schedule();
for (size_t i = 1; i <= iterations; ++i)
{
co_await rb.produce(i);
}
// Wait for the ring buffer to clear all items so its a clean stop.
while (!rb.empty())
{
co_await tp.yield();
}
// Now that the ring buffer is empty signal to all the consumers its time to stop. Note that
// the stop signal works on producers as well, but this example only uses 1 producer.
{
auto scoped_lock = co_await m.lock();
std::cerr << "\nproducer is sending stop signal";
}
rb.stop_signal_waiters();
co_return;
};
auto make_consumer_task = [&](size_t id) -> coro::task<void> {
co_await tp.schedule();
try
{
while (true)
{
auto value = co_await rb.consume();
auto scoped_lock = co_await m.lock();
std::cout << "(id=" << id << ", v=" << value << "), ";
// Mimic doing some work on the consumed value.
co_await tp.yield();
}
}
catch (const coro::stop_signal&)
{
auto scoped_lock = co_await m.lock();
std::cerr << "\nconsumer " << id << " shutting down, stop signal received";
}
co_return;
};
// Create N consumers
for (size_t i = 0; i < consumers; ++i)
{
tasks.emplace_back(make_consumer_task(i));
}
// Create 1 producer.
tasks.emplace_back(make_producer_task());
// Wait for all the values to be produced and consumed through the ring buffer.
coro::sync_wait(coro::when_all(std::move(tasks)));
}