TGViewer
C++ - Reddit C++ - Reddit @r_cpp · 230 subscribers
Post #25032 12
the logical flow.**

# Promise and Future: Bridging Callbacks and Coroutines

This is exactly where [asyncio](https://github.com/Hackerl/asyncio) shines.

`asyncio` is an async framework built on C++20 coroutines and the `libuv` event loop. Its core design idea is simple: use `Promise` and `Future` as a bridge to connect the callback world and the coroutine world.

A `Promise` is an object that can be "resolved" or "rejected". `Future` is its other face — you can `co_await` a `Future`, and the coroutine will automatically resume when the `Promise` is resolved.

Take the `sleep` function as an example, to see how `asyncio` does it:

asyncio::task::Task<void> asyncio::sleep(std::chrono::milliseconds ms) {
Promise<void> promise;

uv_timer_start(timer, [](uv_timer_t *handle) {
// Timer fires, resolve the promise, coroutine resumes
static_cast<Promise<void> *>(handle->data)->resolve();
}, ms.count(), 0);

co_return co_await promise.getFuture();
}

Apply the same treatment to gRPC callbacks: `resolve` or `reject` a `Promise` inside the callback, and `co_await` the corresponding `Future` on the coroutine side. This lets you write what would otherwise require nested callbacks as straight-line code.

# Cancellation Support

Coroutine cancellation is also implemented through the `Promise` mechanism. `asyncio` provides a `Cancellable` wrapper that takes a `Future` and a cancellation function:

co_return co_await asyncio::task::Cancellable{
promise.getFuture(),
[&]() -> std::expected<void, std::error_code> {
// Perform the actual cancellation here
context->TryCancel();
return {};
}
};

When external code calls `task.cancel()`, `asyncio` walks the task chain to find the `Cancellable` currently being awaited and executes its cancellation function. For gRPC, the cancellation function simply calls `context->TryCancel()`. gRPC then handles the cleanup, triggers the `OnDone` callback, the `Promise` is eventually rejected, and the coroutine ends with a cancellation error.

With this mechanism, we can cleanly add cancellation support to any gRPC async operation without introducing any special state variables into business code.

# Defining the Sample Service

Before writing code, let's define a sample service covering all four RPC types:

syntax = "proto3";

package sample;

service SampleService {
// Unary RPC: simplest request-response pattern
rpc Echo(EchoRequest) returns (EchoResponse);

// Server streaming: server continuously pushes data to the client
rpc GetNumbers(GetNumbersRequest) returns (stream Number);

// Client streaming: client continuously sends data, server returns one result
rpc Sum(stream Number) returns (SumResponse);

// Bidirectional streaming: both sides can send and receive continuously
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}

message EchoRequest { string message = 1; }
message EchoResponse { string message = 1; int64 timestamp = 2; }
message GetNumbersRequest { int32 value = 1; int32 count = 2; }
message Number { int32 value = 1; }
message SumResponse { int32 total = 1; int32 count = 2; }
message ChatMessage { string user = 1; string content = 2; int64 timestamp = 3; }

Each RPC pattern has its use: `Echo` is the canonical RPC, `GetNumbers` lets the server stream a batch of data, `Sum` lets the client stream data and get an aggregated result, and `Chat` is the most complex — a bidirectional stream where either side can send at any time.

Let's implement them one by one, starting with the simplest: client Unary RPC.

# Client Unary RPC

Unary RPC is the most straightforward: send one request, receive one response. The corresponding gRPC Reactor method signature is:

void Stub::async::Echo(
grpc::ClientContext *,
const EchoRequest *,
EchoResponse *,
std::function<void(grpc::Status)>
);

gRPC calls the
GitHub GitHub - Hackerl/asyncio: C++23 coroutine network framework C++23 coroutine network framework. Contribute to Hackerl/asyncio development by creating an account on GitHub.
More from @r_cpp
  1. Oct 5, 2026C++ Salary expectations Mods: Please note that I am not looking for jobs or trying to brea…
  2. Oct 5, 2026Embedded C++ Just curious how useful the ability to embed C++ as a scripting language into…
  3. Oct 5, 2026Good Active Open Source Projects Looking For Contributions Hi. I'm wondering if someone wi…
  4. Oct 5, 2026Self Contained Source Groups are amazing I basically adopted this idea from Abseil ([https…
  5. Oct 5, 2026index based for vs for-each https://godbolt.org/z/zh4Kf87M8 https://redd.it/1wksz8y @r_cpp
  6. Oct 5, 2026The Address is Not The Place: Object Residency in C++26 - Laurie Kirk - CppCon 2026 https:…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →