mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Add a quick tour to the readme
This commit is contained in:
parent
33bfc490ef
commit
9593ba120c
195
Readme.md
195
Readme.md
@ -37,15 +37,198 @@ The [documentation](https://naios.github.io/continuable/) offers everything you
|
||||
* [Changelog](https://naios.github.io/continuable/changelog.html)
|
||||
|
||||
|
||||
#### 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:**
|
||||
```cpp
|
||||
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:**
|
||||
```cpp
|
||||
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`:**
|
||||
```cpp
|
||||
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)
|
||||
|
||||
```cpp
|
||||
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`:**
|
||||
```cpp
|
||||
// `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:**
|
||||
```cpp
|
||||
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:**
|
||||
```cpp
|
||||
// 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:
|
||||
|
||||
```cpp
|
||||
int i = co_await cti::make_continuable<int>([](auto&& promise) {
|
||||
promise.set_value(0);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
#### Appearances:
|
||||
|
||||
| [MeetingC++ 2018 Talk](https://naios.github.io/talks/2018-11-17-Meeting-C%2B%2B-Berlin/Continuable.pdf) |
|
||||
| :---: |
|
||||
| [<img alt="Continuable MeetingC++" width="60%" src="https://img.youtube.com/vi/l6-spMA_x6g/0.jpg">](https://www.youtube.com/watch?v=l6-spMA_x6g)] |
|
||||
|
||||
|
||||
#### Issues and contributions
|
||||
|
||||
Issue reports 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.
|
||||
.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user