All Projects → Naios → Continuable

Naios / Continuable

Licence: mit
C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)

Projects that are alternatives of or similar to Continuable

Fibrous
Easily mix asynchronous and synchronous programming styles in node.js.
Stars: ✭ 183 (-72.06%)
Mutual labels:  async, callback
P Map
Map over promises concurrently
Stars: ✭ 639 (-2.44%)
Mutual labels:  async, concurrency
Vkbottle
Homogenic! Customizable asynchronous VK API framework
Stars: ✭ 191 (-70.84%)
Mutual labels:  async, callback
Metasync
Asynchronous Programming Library for JavaScript & Node.js
Stars: ✭ 164 (-74.96%)
Mutual labels:  async, callback
Swoole Src
🚀 Coroutine-based concurrency library for PHP
Stars: ✭ 17,175 (+2522.14%)
Mutual labels:  async, concurrency
Lightio
LightIO is a userland implemented green thread library for ruby
Stars: ✭ 165 (-74.81%)
Mutual labels:  async, concurrency
ProtoPromise
Robust and efficient library for management of asynchronous operations in C#/.Net.
Stars: ✭ 20 (-96.95%)
Mutual labels:  concurrency, callback
Bach
Compose your async functions with elegance.
Stars: ✭ 117 (-82.14%)
Mutual labels:  async, callback
Funfix
Functional Programming Library for JavaScript, TypeScript and Flow ✨⚡️
Stars: ✭ 596 (-9.01%)
Mutual labels:  async, concurrency
Drone Core
The core crate for Drone, an Embedded Operating System.
Stars: ✭ 263 (-59.85%)
Mutual labels:  async, concurrency
Vue Concurrency
A library for encapsulating asynchronous operations and managing concurrency for Vue and Composition API.
Stars: ✭ 147 (-77.56%)
Mutual labels:  async, concurrency
Ava
Node.js test runner that lets you develop with confidence 🚀
Stars: ✭ 19,458 (+2870.69%)
Mutual labels:  async, concurrency
Asyncninja
A complete set of primitives for concurrency and reactive programming on Swift
Stars: ✭ 146 (-77.71%)
Mutual labels:  async, concurrency
Smol
A small and fast async runtime for Rust
Stars: ✭ 2,206 (+236.79%)
Mutual labels:  async, concurrency
Tascalate Concurrent
Implementation of blocking (IO-Bound) cancellable java.util.concurrent.CompletionStage and related extensions to java.util.concurrent.ExecutorService-s
Stars: ✭ 144 (-78.02%)
Mutual labels:  async, concurrency
Pyee
A port of Node.js's EventEmitter to python
Stars: ✭ 236 (-63.97%)
Mutual labels:  async, concurrency
Swimmer
🏊 Swimmer - An async task pooling and throttling utility for JS
Stars: ✭ 94 (-85.65%)
Mutual labels:  async, concurrency
Drone
CLI utility for Drone, an Embedded Operating System.
Stars: ✭ 114 (-82.6%)
Mutual labels:  async, concurrency
Promise Pool
Map-like, concurrent promise processing
Stars: ✭ 258 (-60.61%)
Mutual labels:  async, concurrency
Promise Fun
Promise packages, patterns, chat, and tutorials
Stars: ✭ 3,779 (+476.95%)
Mutual labels:  async, concurrency

Continuable

Current version Travic-CI build status AppVeyor CI status MIT Licensed Documentation Try continuable online Compiler explorer


Continuable is a C++14 library that provides full support for:

  • lazy async continuation chaining based on callbacks (then) and expression templates, callbacks are wrapped nicely as promises.
  • no enforced type-erasure which means we need less heap allocations than comparable libraries, strictly following the "don't pay for what you don't use" principle.
  • support for all, any and sequential connections between continuables through expressive operator overloads &&, || and >> as well as free functions when_all, when_any and when_seq.
  • asynchronous error handling through exceptions, error codes and user defined types.
  • syntactic sugar for instance: partial invocation, tuple unpacking, co_await support and executors.
  • encapsuled from any runtime, larger framework or executors makes it possible to use continuable even in smaller or esoteric usage scenarios.

Getting started:

The documentation offers everything you need:

Issues and contributions

Issue reports and questions are accepted through the Github issue tracker as well as pull requests. Every contribution is welcome! Don't hesitate to ask for help if you need any support in improving the implementation or if you have any troubles in using the library

Quick Tour

  • Create a continuable through make_continuable which returns a promise on invocation:

    auto http_request(std::string url) {
      return cti::make_continuable<std::string>([url = std::move(url)](auto&& promise) {
        // Perform the actual request through a different library,
        // resolve the promise upon completion of the task.
        promise.set_value("<html> ... </html>");
        // or: promise.set_exception(std::make_exception_ptr(std::exception("Some error")));
        // or: promise.set_canceled();
      });
    }
    
    auto mysql_query(std::string query) {
      return cti::make_continuable<result_set, bool>([url = std::move(url)](auto&& promise) {
        //                         ^^^^^^^^^^^^^^ multiple result types
      });
    }
    
    auto do_sth() {
      return cti::make_continuable<void>([](auto&& promise) {
        //                         ^^^^ no result at all
      });
    }
    
    auto run_it() {
      return async([] {
        // Directly start with a handler
      });
    }
    
    continuable<> run_it() { // With type erasure
      return async([] {
    
      });
    }
    
  • Attach your continuations through then, supports multiple results and partial handlers:

    mysql_query("SELECT `id`, `name` FROM `users`")
      .then([](result_set users) {
        // Return the next continuable to process ...
        return mysql_query("SELECT `id` name FROM `sessions`");
      })
      .then([](result_set sessions) {
        // ... or pass multiple values to the next callback using tuples or pairs ...
        return std::make_tuple(std::move(sessions), true);
      })
      .then([](result_set sessions, bool is_ok) {
        // ... or pass a single value to the next callback ...
        return 10;
      })
      .then([](auto value) {
        //     ^^^^ Templated callbacks are possible too
      })
      // ... you may even pass continuables to the `then` method directly:
      .then(mysql_query("SELECT * `statistics`"))
      .then([](result_set result) {
        // ...
          return "Hi";
      })
      .then([] /*(std::string result) */ { // Handlers can accept a partial set of arguments{
        // ...
      });
    
  • Handle failures through fail or next:

    http_request("example.com")
      .then([] {
        throw std::exception("Some error");
      })
      .fail([] (std::exception_ptr ptr) {
        if (ptr) {
          try {
            std::rethrow_exception(ptr);
          } catch(std::exception const& e) {
            // Handle the exception or error code here
          }
        }
      });
    
  • Dispatch continuations through a specific executor (possibly on a different thread or later)

    auto executor = [](auto&& work) {
      // Dispatch the work here, store it for later invocation or move it to another thread.
      std::forward<decltype(work)>(work)();
    };
    
    read_file("entries.csv")
      .then([](Buffer buffer) {
        // ...
      }, executor);
    //   ^^^^^^^^
    
  • Connect continuables through when_all, when_any or when_seq:

    // `all` of connections:
    (http_request("github.com") && http_request("example.com") && http_request("wikipedia.org"))
      .then([](std::string github, std::string example, std::string wikipedia) {
        // The callback is called with the response of github,
        // example and wikipedia.
      });
    
    // `any` of connections:
    (http_request("github.com") || http_request("example.com") || http_request("wikipedia.org"))
      .then([](std::string github_or_example_or_wikipedia) {
        // The callback is called with the first response of either github,
        // example or wikipedia.
      });
    
    // `sequence` of connections:
    (http_request("github.com") >> http_request("example.com") >> http_request("wikipedia.org"))
      .then([](std::string github, std::string example, std::string wikipedia) {
        // The requests are invoked sequentially
      });
    
    // Mixed logical connections:
    (http_request("github.com") && (http_request("example.com") || http_request("wikipedia.org")))
      .then([](std::string github, std::string example_or_wikipedia) {
        // The callback is called with the response of github for sure
        // and the second parameter represents the response of example or wikipedia.
      });
    
    // There are helper functions for connecting continuables:
    auto all = cti::when_all(http_request("github.com"), http_request("example.com"));
    auto any = cti::when_any(http_request("github.com"), http_request("example.com"));
    auto seq = cti::when_seq(http_request("github.com"), http_request("example.com"));
    
  • Deal with multiple result variables through result and recover from failures:

    make_exceptional_continuable<void>(std::make_exception_ptr(std::exception("Some error"))
      .fail([] (std::exception_ptr ptr) {
        return recover();
      })
      .then([] () -> result<> {
        // We recovered from the failure and proceeding normally
    
        // Will yield a default constructed exception type to signal cancellation
        return cancel();
      });
    
  • promisify your existing code or use the (asio) completion token integration:

    // Promisification of your existing code that accepts callbacks
    auto async_resolve(std::string host, std::string service) {
      return cti::promisify<asio::ip::udp::resolver::iterator>::from(
          [&](auto&&... args) {
            resolver_.async_resolve(std::forward<decltype(args)>(args)...);
          },
          std::move(host), std::move(service));
    }
    
    // (boost) asio completion token integration
    asio::io_context io_context;
    asio::steady_timer steady_timer(io_context);
    
    steady_timer.expires_after(std::chrono::seconds(5));
    steady_timer.async_wait(cti::use_continuable)
      .then([] {
        // Is called after 5s
      });
    
  • C++20 Coroutine support:

    (co_await and co_return) are supported by continuable when the underlying toolchain supports the TS. Currently this works in MSVC 2017 and Clang 5.0. You have to enable this capability through the CTI_CONTINUABLE_WITH_AWAIT define in CMake:

    int i = co_await cti::make_continuable<int>([](auto&& promise) {
      promise.set_value(0);
    });
    

Appearances:

MeetingC++ 2018 Talk
Continuable MeetingC++]

.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].