{"id":13418877,"url":"https://github.com/Naios/continuable","last_synced_at":"2025-03-15T04:31:02.618Z","repository":{"id":33170222,"uuid":"36811307","full_name":"Naios/continuable","owner":"Naios","description":"C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)","archived":false,"fork":false,"pushed_at":"2023-09-12T17:14:28.000Z","size":1859,"stargazers_count":819,"open_issues_count":18,"forks_count":44,"subscribers_count":37,"default_branch":"master","last_synced_at":"2024-07-31T22:44:30.259Z","etag":null,"topics":["async","async-continuation-chains","callback","concurrency","continuable-library","continuation-logic","efficient-implementations","syntax-sugar"],"latest_commit_sha":null,"homepage":"https://naios.github.io/continuable/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Naios.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2015-06-03T15:06:03.000Z","updated_at":"2024-07-23T08:30:31.000Z","dependencies_parsed_at":"2023-01-14T23:46:11.444Z","dependency_job_id":null,"html_url":"https://github.com/Naios/continuable","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Fcontinuable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Fcontinuable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Fcontinuable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Fcontinuable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Naios","download_url":"https://codeload.github.com/Naios/continuable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221536665,"owners_count":16839544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","async-continuation-chains","callback","concurrency","continuable-library","continuation-logic","efficient-implementations","syntax-sugar"],"created_at":"2024-07-30T22:01:08.260Z","updated_at":"2024-10-26T13:31:58.513Z","avatar_url":"https://github.com/Naios.png","language":"C++","funding_links":[],"categories":["TODO scan for Android support in followings"],"sub_categories":[],"readme":"\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://naios.github.io/continuable/\"\u003e\n    \u003cimg alt=\"Continuable\" src=\"https://raw.githubusercontent.com/Naios/continuable/master/doc/slideshow.gif\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://naios.github.io/continuable/changelog.html#changelog-versions-4-0-0\"\u003e\u003cimg alt=\"Current version\" src=\"https://img.shields.io/badge/Version-4.0.0-0091EA.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://ci.appveyor.com/project/Naios/continuable/branch/master\"\u003e\u003cimg alt=\"AppVeyor CI status\" src=\"https://ci.appveyor.com/api/projects/status/328ta3r5x92f3byv/branch/master?svg=true\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"MIT Licensed\" src=\"https://img.shields.io/badge/License-MIT-00838F.svg\"\u003e\n  \u003ca href=\"https://naios.github.io/continuable/\"\u003e\u003cimg alt=\"Documentation\" src=\"https://img.shields.io/badge/Documentation-Doxygen-26A69A.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://wandbox.org/permlink/EDr7u2P5HXs2W6p1\"\u003e\u003cimg alt=\"Try continuable online\" src=\"https://img.shields.io/badge/Run-online-4DB6AC.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://godbolt.org/g/iyE4Ww\"\u003e\u003cimg alt=\"Compiler explorer\" src=\"https://img.shields.io/badge/Compiler-explorer-58CEC2.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n------\n\n#### Continuable is a C++14 library that provides full support for:\n\n* lazy async continuation chaining based on callbacks (**then**) and expression templates, callbacks are wrapped nicely as **promises**.\n* **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.\n* support for *all*, *any* and *sequential* connections between continuables through expressive operator overloads **\u0026\u0026**, **||** and **\u003e\u003e** as well as free functions **when_all**, **when_any** and **when_seq**.\n* asynchronous **error handling** through **exceptions**, **error codes** and **user defined types**.\n* syntactic sugar for instance: **partial invocation**, **tuple unpacking**, `co_await` support and **executors**.\n* **encapsuled from any runtime**, larger framework or executors makes it possible to use continuable even in smaller or esoteric usage scenarios.\n\n------\n\n#### Getting started:\n\nThe [documentation](https://naios.github.io/continuable/) offers everything you need:\n* [Installation guide](https://naios.github.io/continuable/installation.html)\n* [Usage tutorial](https://naios.github.io/continuable/tutorial.html)\n* [Configuration explanation](https://naios.github.io/continuable/configuration.html)\n* [Changelog](https://naios.github.io/continuable/changelog.html)\n\n\n#### Issues and contributions\n\nIssue reports and questions are accepted through the Github issue tracker as well as pull requests.\nEvery contribution is welcome! Don't hesitate to ask for help if you need any support\nin improving the implementation or if you have any troubles in using the library\n\n#### Quick Tour\n\n- **Create a continuable through `make_continuable` which returns a promise on invocation:**\n  ```cpp\n  auto http_request(std::string url) {\n    return cti::make_continuable\u003cstd::string\u003e([url = std::move(url)](auto\u0026\u0026 promise) {\n      // Perform the actual request through a different library,\n      // resolve the promise upon completion of the task.\n      promise.set_value(\"\u003chtml\u003e ... \u003c/html\u003e\");\n      // or: promise.set_exception(std::make_exception_ptr(std::exception(\"Some error\")));\n      // or: promise.set_canceled();\n    });\n  }\n\n  auto mysql_query(std::string query) {\n    return cti::make_continuable\u003cresult_set, bool\u003e([url = std::move(url)](auto\u0026\u0026 promise) {\n      //                         ^^^^^^^^^^^^^^ multiple result types\n    });\n  }\n\n  auto do_sth() {\n    return cti::make_continuable\u003cvoid\u003e([](auto\u0026\u0026 promise) {\n      //                         ^^^^ no result at all\n    });\n  }\n\n  auto run_it() {\n    return async([] {\n      // Directly start with a handler\n    });\n  }\n\n  continuable\u003c\u003e run_it() { // With type erasure\n    return async([] {\n\n    });\n  }\n  ```\n\n- **Attach your continuations through `then`, supports multiple results and partial handlers:**\n  ```cpp\n  mysql_query(\"SELECT `id`, `name` FROM `users`\")\n    .then([](result_set users) {\n      // Return the next continuable to process ...\n      return mysql_query(\"SELECT `id` name FROM `sessions`\");\n    })\n    .then([](result_set sessions) {\n      // ... or pass multiple values to the next callback using tuples or pairs ...\n      return std::make_tuple(std::move(sessions), true);\n    })\n    .then([](result_set sessions, bool is_ok) {\n      // ... or pass a single value to the next callback ...\n      return 10;\n    })\n    .then([](auto value) {\n      //     ^^^^ Templated callbacks are possible too\n    })\n    // ... you may even pass continuables to the `then` method directly:\n    .then(mysql_query(\"SELECT * `statistics`\"))\n    .then([](result_set result) {\n      // ...\n        return \"Hi\";\n    })\n    .then([] /*(std::string result) */ { // Handlers can accept a partial set of arguments{\n      // ...\n    });\n  ```\n\n- **Handle failures through `fail` or `next`:**\n  ```cpp\n  http_request(\"example.com\")\n    .then([] {\n      throw std::exception(\"Some error\");\n    })\n    .fail([] (std::exception_ptr ptr) {\n      if (ptr) {\n        try {\n          std::rethrow_exception(ptr);\n        } catch(std::exception const\u0026 e) {\n          // Handle the exception or error code here\n        }\n      }\n    });\n  ```\n\n- **Dispatch continuations through a specific executor** (possibly on a different thread or later)\n\n  ```cpp\n  auto executor = [](auto\u0026\u0026 work) {\n    // Dispatch the work here, store it for later invocation or move it to another thread.\n    std::forward\u003cdecltype(work)\u003e(work)();\n  };\n\n  read_file(\"entries.csv\")\n    .then([](Buffer buffer) {\n      // ...\n    }, executor);\n  //   ^^^^^^^^\n  ```\n\n- **Connect continuables through `when_all`, `when_any` or `when_seq`:**\n  ```cpp\n  // `all` of connections:\n  (http_request(\"github.com\") \u0026\u0026 http_request(\"example.com\") \u0026\u0026 http_request(\"wikipedia.org\"))\n    .then([](std::string github, std::string example, std::string wikipedia) {\n      // The callback is called with the response of github,\n      // example and wikipedia.\n    });\n\n  // `any` of connections:\n  (http_request(\"github.com\") || http_request(\"example.com\") || http_request(\"wikipedia.org\"))\n    .then([](std::string github_or_example_or_wikipedia) {\n      // The callback is called with the first response of either github,\n      // example or wikipedia.\n    });\n\n  // `sequence` of connections:\n  (http_request(\"github.com\") \u003e\u003e http_request(\"example.com\") \u003e\u003e http_request(\"wikipedia.org\"))\n    .then([](std::string github, std::string example, std::string wikipedia) {\n      // The requests are invoked sequentially\n    });\n\n  // Mixed logical connections:\n  (http_request(\"github.com\") \u0026\u0026 (http_request(\"example.com\") || http_request(\"wikipedia.org\")))\n    .then([](std::string github, std::string example_or_wikipedia) {\n      // The callback is called with the response of github for sure\n      // and the second parameter represents the response of example or wikipedia.\n    });\n\n  // There are helper functions for connecting continuables:\n  auto all = cti::when_all(http_request(\"github.com\"), http_request(\"example.com\"));\n  auto any = cti::when_any(http_request(\"github.com\"), http_request(\"example.com\"));\n  auto seq = cti::when_seq(http_request(\"github.com\"), http_request(\"example.com\"));\n  ```\n\n- **Deal with multiple result variables through `result` and `recover` from failures:**\n  ```cpp\n  make_exceptional_continuable\u003cvoid\u003e(std::make_exception_ptr(std::exception(\"Some error\"))\n    .fail([] (std::exception_ptr ptr) {\n      return recover();\n    })\n    .then([] () -\u003e result\u003c\u003e {\n      // We recovered from the failure and proceeding normally\n\n      // Will yield a default constructed exception type to signal cancellation\n      return cancel();\n    });\n  ```\n\n- **`promisify` your existing code or use the (asio) completion token integration:**\n  ```cpp\n  // Promisification of your existing code that accepts callbacks\n  auto async_resolve(std::string host, std::string service) {\n    return cti::promisify\u003casio::ip::udp::resolver::iterator\u003e::from(\n        [\u0026](auto\u0026\u0026... args) {\n          resolver_.async_resolve(std::forward\u003cdecltype(args)\u003e(args)...);\n        },\n        std::move(host), std::move(service));\n  }\n\n  // (boost) asio completion token integration\n  asio::io_context io_context;\n  asio::steady_timer steady_timer(io_context);\n\n  steady_timer.expires_after(std::chrono::seconds(5));\n  steady_timer.async_wait(cti::use_continuable)\n    .then([] {\n      // Is called after 5s\n    });\n  ```\n\n- **C++20 Coroutine support:**\n\n  (`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:\n\n  ```cpp\n  int i = co_await cti::make_continuable\u003cint\u003e([](auto\u0026\u0026 promise) {\n    promise.set_value(0);\n  });\n  ```\n\n\n#### Appearances:\n\n| [MeetingC++ 2018 Talk](https://naios.github.io/talks/2018-11-17-Meeting-C%2B%2B-Berlin/Continuable.pdf) |\n| :---: |\n| [\u003cimg alt=\"Continuable MeetingC++\" width=\"60%\" src=\"https://img.youtube.com/vi/l6-spMA_x6g/0.jpg\"\u003e](https://www.youtube.com/watch?v=l6-spMA_x6g)] |\n\n.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNaios%2Fcontinuable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNaios%2Fcontinuable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNaios%2Fcontinuable/lists"}