{"id":19159884,"url":"https://github.com/tzcnt/tmc-asio","last_synced_at":"2026-02-02T00:10:36.535Z","repository":{"id":195482727,"uuid":"692634117","full_name":"tzcnt/tmc-asio","owner":"tzcnt","description":"Asio integration for the TooManyCooks runtime","archived":false,"fork":false,"pushed_at":"2025-02-09T05:30:24.000Z","size":35,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-09T06:23:26.872Z","etag":null,"topics":["asio","coroutines","cpp","cpp20"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tzcnt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-17T05:08:12.000Z","updated_at":"2025-02-09T05:30:27.000Z","dependencies_parsed_at":"2024-01-25T04:30:20.899Z","dependency_job_id":"744d8e55-6f30-45c4-9be1-b4a2a066cefa","html_url":"https://github.com/tzcnt/tmc-asio","commit_stats":null,"previous_names":["tzcnt/tmc-asio"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tzcnt%2Ftmc-asio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tzcnt%2Ftmc-asio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tzcnt%2Ftmc-asio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tzcnt%2Ftmc-asio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tzcnt","download_url":"https://codeload.github.com/tzcnt/tmc-asio/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240245909,"owners_count":19771028,"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":["asio","coroutines","cpp","cpp20"],"created_at":"2024-11-09T08:52:41.972Z","updated_at":"2026-02-02T00:10:36.531Z","avatar_url":"https://github.com/tzcnt.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## tmc-asio\ntmc-asio provides [Asio](https://think-async.com/Asio/) integration functionality for the [TooManyCooks](https://github.com/tzcnt/TooManyCooks) async runtime.\n\nSee https://github.com/tzcnt/tmc-examples/tree/main/examples/asio for examples of how to use this.\n\nThis is a header-only library. It respects the following preprocessor directive configurations:\n- `TMC_USE_BOOST_ASIO`: Integrate with boost::asio instead of standalone Asio.\n\nThis repository provides 2 headers. Each file is standalone (does not depend on the other).\n\n### aw_asio.hpp\nProvides a completion token `tmc::aw_asio` that can be passed to any Asio async function to turn it into a TMC awaitable. The parameters that Asio would provide to a callback completion token will instead be returned as a tuple from the `co_await` expression.\n\nThis awaitable can be used from within any C++20 coroutine that can be converted to a std::coroutine_handle\u003c\u003e. If that coroutine is running on a thread attached to an executor that provides a specialization of `tmc::detail::executor_traits` (all of the TMC executors provide this), then when the awaitable completes, it will be resumed back on its original executor, at its original priority.\n\nA typical use case would be to `co_await` an Asio operation from within the TMC CPU executor; after the Asio operation completes, the coroutine will resume back on the TMC CPU executor. If you prefer to have the coroutine resume inline on the Asio executor, you can specify that by calling `.resume_on(tmc::asio_executor())` on the awaitable before awaiting it.\n\nFor example:\n```cpp\n#include \"asio.hpp\" // Asio library header\n#include \"tmc/task.hpp\"\n#include \"tmc/asio/aw_asio.hpp\"\n\ntmc::task\u003cvoid\u003e handler(asio::ip::tcp::socket sock) {\n  char data[4096];\n  auto buf = asio::buffer(data);\n  auto [error, bytes_read] = co_await sock.async_read_some(buf, tmc::aw_asio);\n  // Do something with buf...\n}\n```\n\n### ex_asio.hpp\nProvides the executor type `tmc::ex_asio`. This executor transparently wraps a single-threaded `asio::io_context`, so that it can be provided directly to any Asio calls. It also functions as a TMC executor by providing a specialization of `tmc::detail::executor_traits`.\n\nA global instance of this is provided at `tmc::asio_executor()`. The global instance does not start running until `init()` is called on it - so you can choose to construct your own instance instead. Multiple instances of `tmc::ex_asio` will not conflict with each other.\n\n```cpp\n#include \u003casio.hpp\u003e // Asio library header\n#include \"tmc/ex_cpu.hpp\"\n#include \"tmc/fork_group.hpp\"\n#include \"tmc/task.hpp\"\n#include \"tmc/asio/aw_asio.hpp\"\n#include \"tmc/asio/ex_asio.hpp\"\nint main() {\n  tmc::asio_executor().init();\n  return tmc::async_main([]() -\u003e tmc::task\u003cint\u003e {\n    auto fg = tmc::fork_group();\n\n    asio::ip::tcp::acceptor acceptor(tmc::asio_executor(), {asio::ip::tcp::v4(), 55555});\n    while (true) {\n      auto [error, sock] = co_await acceptor.async_accept(tmc::aw_asio);\n      if (error) {\n        break;\n      }\n      // Fork the handler from the prior example, which starts running concurrently.\n      // This task's loop will continue and accept more connections.\n      fg.fork(handler(std::move(sock)));\n    }\n\n    // Wait for all handlers to complete before returning.\n    co_await std::move(fg);\n\n    co_return 0;\n  }());\n}\n```\n\n### Integrating with an existing Asio setup\nUse of the `ex_asio.hpp` header and the global executor that it provides is not required. TMC can integrate with an existing standalone executor via `aw_asio.hpp` alone; however, under these conditions, you will be limited to the following functionality:\n- From a coroutine running on the TMC executor, initiating an async operation on Asio and `co_await`ing it using the `tmc::aw_asio` completion token. Once the Asio operation completes, the coroutine will be posted back to the TMC executor queue to be resumed.\n\n\nTo fully integrate your existing Asio setup with TMC, you must provide a specialization of `tmc::detail::executor_traits`, and set the `tmc::detail::this_thread::executor` pointer on each of its threads (see `tmc::ex_asio.init_thread_locals()`). This unlocks the following additional functionality:\n- `co_await`ing a `tmc::aw_asio` operation from a coroutine running on the Asio executor and having it resume inline on the Asio executor.\n- `co_await`ing a `tmc::aw_asio` operation from a coroutine running on the TMC executor and modifying it via the `.resume_on()` function to have it resume inline on the Asio executor, rather than back on the TMC executor.\n- Using the standalone `co_await tmc::resume_on()` function to switch a running coroutine onto the Asio executor at any time.\n- Using the standalone `co_await tmc::enter()` function to switch a running coroutine onto the Asio executor at any time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftzcnt%2Ftmc-asio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftzcnt%2Ftmc-asio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftzcnt%2Ftmc-asio/lists"}