Skip to content

Latest commit

Β 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

potok 🌊

A C++20 coroutine runtime for structured concurrency β€” tasks, a thread-pool scheduler, when_all, channels, async mutex/event and generators. Header-first, zero dependencies.

C++20 License: MIT build: CMake deps: none tests


What is it?

C++20 gave the language coroutines but almost no library to use them. potok fills that gap with a small, composable runtime in the spirit of cppcoro: lazy task<T>s, an executor to run them on, and the combinators to structure concurrent work β€” all with clean RAII and exception propagation, and no dependencies beyond the standard library.

#include <potok/potok.hpp>
using namespace potok;
using namespace std::chrono_literals;

task<int> square(static_thread_pool& pool, int x) {
    co_await pool.schedule();          // hop onto a worker thread
    co_return x * x;
}

task<int> sum_of_squares(static_thread_pool& pool) {
    std::vector<task<int>> work;
    for (int i = 1; i <= 10; ++i) work.push_back(square(pool, i));
    auto results = co_await when_all(std::move(work));   // run them in parallel
    int total = 0;
    for (int r : results) total += r;
    co_return total;                    // 385
}

int main() {
    static_thread_pool pool;
    int total = sync_wait(sum_of_squares(pool));   // bridge sync -> async
}

Components

Type What it gives you
task<T> A lazy coroutine. Starts when awaited (symmetric transfer, no wasted frames), propagates results and exceptions to the awaiter.
sync_wait(awaitable) Runs an awaitable to completion and blocks until it returns β€” the door from main() into async code.
static_thread_pool A pool of worker threads plus a timer. co_await pool.schedule() resumes on a worker; co_await pool.schedule_after(d) resumes after a delay.
when_all(...) Await many tasks concurrently; returns a vector or tuple of results, rethrowing the first exception.
channel<T> A bounded MPMC queue coroutines pass values through (co_await ch.send/recv), with back-pressure and close semantics.
async_mutex A mutex you co_await instead of blocking a thread; yields an RAII guard.
async_manual_reset_event A one-to-many signal coroutines can await.
generator<T> A lazy pull sequence built with co_yield, usable in a range-for.
detached_task Fire-and-forget background coroutine.

Why it reads nicely

  • Structured. when_all ties concurrent lifetimes together; results and errors come back to one place instead of leaking through callbacks.
  • No callback soup. Async code is written top-to-bottom with co_await.
  • Composable. Everything is an awaitable, so the pieces combine: co_await pool.schedule_after(50ms), co_await ch.recv(), co_await mutex.lock().
  • Exception-safe. Exceptions propagate across co_await and out of when_all / sync_wait just like ordinary calls.

A pipeline in full

task<void> produce(static_thread_pool& pool, channel<std::string>& ch) {
    co_await pool.schedule();
    for (int i = 0; i < 5; ++i) co_await ch.send("msg#" + std::to_string(i));
    ch.close();
}

task<void> consume(static_thread_pool& pool, channel<std::string>& ch) {
    co_await pool.schedule();
    while (auto msg = co_await ch.recv())   // nullopt once closed & drained
        handle(*msg);
}

task<void> run(static_thread_pool& pool) {
    channel<std::string> ch(2);             // small buffer => real back-pressure
    std::vector<task<void>> both;
    both.push_back(produce(pool, ch));
    both.push_back(consume(pool, ch));
    co_await when_all(std::move(both));
}

Build

Needs a C++20 compiler with coroutines (GCC β‰₯ 10, Clang β‰₯ 14, MSVC β‰₯ 19.28) and CMake β‰₯ 3.14. No third-party dependencies.

git clone https://github.com/VirusAid/potok.git
cd potok
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build --output-on-failure

Use it in your project (CMake)

add_subdirectory(potok)
target_link_libraries(my_app PRIVATE potok::potok)

The runtime is header-first; only the thread pool is compiled (one small .cpp).

Design notes & limits

  • Scheduling is a simple shared FIFO run-queue β€” fair and correct, not a work-stealing deque. Great up to moderate core counts.
  • channel and the async primitives guard their state with a std::mutex and resume waiters inline; ideal for coordination, not for microsecond-latency hot loops.
  • No OS I/O reactor (epoll/IOCP) yet: potok schedules CPU work and timers. Networking on top of the same awaitable model is a natural next layer.

It is a real, tested runtime β€” the concurrency tests (an 8-worker Γ— 500-iter mutex stress, a 1000-item channel pipeline) pass repeatably β€” but young. See SECURITY.md to report issues.

License

MIT β€” see LICENSE. Free for any use, including commercial.

About

🌊 potok β€” a C++20 coroutine runtime for structured concurrency: tasks, a thread-pool scheduler, when_all, channels, async mutex/event and generators. Header-first, zero dependencies.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages