Skip to content

electronicarts/minicoros

Repository files navigation

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 and std::function implementations that have larger SBO, but no such support exists in Minicoros
    • Less flexibility in values accepted to/from callbacks
  • 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.

Examples

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` 
}

Contributing

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

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages