Minicoros
is a C++17 header-only library that implements future chains (similar to coroutines). Heavily inspired by Denis Blank's (Naios) Continuable library but with the following differences:
- Faster compilation time through simpler code:
- Minicoros executes two calls to
operator new
for each.then
handler, as opposed to the Continuable library that opts for zero-cost abstractions. Allocations can possibly be mitigated by using pooled allocators andstd::function
implementations that have larger SBO, but no such support exists in Minicoros - Less flexibility in values accepted to/from callbacks
- Minicoros executes two calls to
- More opinionated, which should make it easier to use
- No threading support, no exceptions, uses
std::function
Why use Minicoros over Continuables? Minicoros is much friendlier to the compiler; preliminary measurements point to code using Minicoros compiling in 1/2 to 1/4 of the time Continuable uses and that Minicoros scales much better for longer chains. Compiler memory usage follows a similar pattern. (TODO: measure)
Unfortunately there's no support for C++20 coroutines yet, but that will be added.
mc::future<int> sum1(int o1, int o2) {
// Return a future that synchronously/immediately returns a successful value
return mc::make_successful_future<int>(o1 + o2);
}
mc::future<int> sum2(int o1, int o2) {
// A future is backed by a promise -- the promise resolves the future
return mc::future<int>([o1, o2] (mc::promise<int> promise) {
// This lambda will get invoked lazily at a later point
promise(o1 + o2);
});
}
void main() {
sum1(4, 10)
.then([](int sum) -> mc::result<int> { // Specify the return type
if (sum != 14) {
// Preferred way of returning an error. With `failure`, you don't have to re-type the return type
return mc::failure(EBADSUM);
}
// ... or by returning a future that fails:
if (sum != 14)
return mc::make_failed_future<int>(EBADSUM);
return sum * 2;
})
.fail([](int error) {
return failure(error); // Rethrow
})
.fail([](int error) -> mc::result<void> { // Explicitly recover from the error
return {};
})
.then([] () -> mc::result<int, int> {
return sum1(1, 3) && sum2(1, 3);
})
.then([] (int s1, int s2) {
// Actually, it's alright not specifying mc::result on .thens that return void
ASSERT_EQ(s1, s2);
})
.ignore_result(); // To protect against forgetting to handle errors, a chain either needs to be returned
// from the current function, or finalized with `done`
}
Before you can contribute, EA must have a Contributor License Agreement (CLA) on file that has been signed by each contributor. You can sign here: Go to CLA