mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Cleanup the readme
This commit is contained in:
parent
2d1fda228f
commit
27aafa2f0e
465
Readme.md
465
Readme.md
@ -1,443 +1,42 @@
|
|||||||

|
|
||||||
|
|
||||||
[](https://github.com/Naios/continuable/releases/tag/2.0.0) [](https://travis-ci.org/Naios/continuable) [](https://ci.appveyor.com/project/Naios/continuable/branch/master)  [](https://naios.github.io/continuable/) [](http://melpon.org/wandbox/permlink/xVM2szjDLEge3YLV)
|
<p align="center">
|
||||||
|
<a href="https://naios.github.io/continuable/">
|
||||||
|
<img alt="Continuable" src="https://raw.githubusercontent.com/Naios/continuable/master/doc/slideshow.gif">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://naios.github.io/continuable/changelog.html#changelog-versions-3-0-0"><img alt="Current version" src="https://img.shields.io/badge/Version-3.0.0-0091EA.svg"></a>
|
||||||
|
<a href="https://travis-ci.org/Naios/continuable"><img alt="Travic-CI build status" src="https://travis-ci.org/Naios/continuable.svg?branch=master"></a>
|
||||||
|
<a href="https://ci.appveyor.com/project/Naios/continuable/branch/master"><img alt="AppVeyor CI status" src="https://ci.appveyor.com/api/projects/status/328ta3r5x92f3byv/branch/master?svg=true"></a>
|
||||||
|
<img alt="MIT Licensed" src="https://img.shields.io/badge/License-MIT-00838F.svg">
|
||||||
|
<a href="https://naios.github.io/continuable/"><img alt="Documentation" src="https://img.shields.io/badge/Documentation-Doxygen-26A69A.svg"></a>
|
||||||
|
<a href="http://melpon.org/wandbox/permlink/xVM2szjDLEge3YLV"><img alt="Try continuable online" src="https://img.shields.io/badge/Try-online-4DB6AC.svg"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
#### Continuable is a C++14 library that provides full support for:
|
||||||
|
|
||||||
This library provides full feature support of:
|
* 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.
|
||||||
|
|
||||||
* 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**, strictly following the **"don't pay for what you don't use"** principle.
|
|
||||||
* support for **connections** between continuables through an **all, any or sequential** strategy through expressive operator overloads **&&**, **||** and **>>**.
|
|
||||||
* **error handling** through exceptions or custom types.
|
|
||||||
* **syntactic sugar** for instance: **partial invocation**, **tuple unpacking** and **executors**.
|
|
||||||
|
|
||||||
|
#### Getting started:
|
||||||
|
|
||||||
|
The [documentation](https://naios.github.io/continuable/) offers everything you need:
|
||||||
|
* [Installation guide](https://naios.github.io/continuable/installation.html)
|
||||||
|
* [Usage tutorial](https://naios.github.io/continuable/tutorial.html)
|
||||||
|
* [Configuration explanation](https://naios.github.io/continuable/configuration.html)
|
||||||
|
* [Changelog](https://naios.github.io/continuable/changelog.html)
|
||||||
|
|
||||||
## The basics
|
#### Issues and contributions
|
||||||
|
|
||||||
|
|
||||||
* Supply a continuable which is invoked lazily upon request:
|
|
||||||
```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(...);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Continue the continuation using `.then(...)` and `.fail(...)`, exceptions are passed to the first available handler:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
http_request("github.com")
|
|
||||||
.then([] (std::string result) {
|
|
||||||
// Do something...
|
|
||||||
return http_request("travis-ci.org")
|
|
||||||
})
|
|
||||||
.then([] (std::string result) {
|
|
||||||
// Handle the response from 'travis-ci.org'
|
|
||||||
})
|
|
||||||
.fail([] (std::exception_ptr ptr) {
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(ptr);
|
|
||||||
} catch(std::exception const& e) {
|
|
||||||
// Handle the exception or error code here
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
* Create connections between the continuables and use its compound result:
|
|
||||||
```cpp
|
|
||||||
(http_request("github.com") && (http_request("travis-ci.org") || http_request("atom.io")))
|
|
||||||
.then([](std::string github, std::string travis_or_atom) {
|
|
||||||
// The promise is called with the response of github and travis or atom.
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
- [Installation](#installation)
|
|
||||||
- [How-to use](#how-to-use)
|
|
||||||
- [Building the unit-tests](#building-the-unit-tests)
|
|
||||||
- [Stability and version](#stability-and-version)
|
|
||||||
- [Quick reference](#quick-reference)
|
|
||||||
- [Creating Continuables](#creating-continuables)
|
|
||||||
- [Chaining Continuables](#chaining-continuables)
|
|
||||||
- [Providing helper functions](#providing-helper-functions)
|
|
||||||
- [Error handling](#error-handling)
|
|
||||||
- [Connecting Continuables {all, any or sequential}](#connecting-continuables-all-any-or-sequential)
|
|
||||||
- [Partial argument application](#partial-argument-application)
|
|
||||||
- [Dispatching callbacks through a specific executor](#dispatching-callbacks-through-a-specific-executor)
|
|
||||||
- [Type erasure](#type-erasure)
|
|
||||||
- [Coroutines](#coroutines)
|
|
||||||
- [Future conversion](#future-conversion)
|
|
||||||
- [Compatibility](#compatibility)
|
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### How-to use
|
|
||||||
|
|
||||||
As mentioned earlier the library is header-only. There is a cmake project provided for simple setup:
|
|
||||||
|
|
||||||
#### As git submodule
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Shell:
|
|
||||||
git submodule add https://github.com/Naios/continuable.git
|
|
||||||
```
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
# CMake file:
|
|
||||||
add_subdirectory(continuable)
|
|
||||||
# continuable provides an interface target which makes it's
|
|
||||||
# headers available to all projects using the continuable library.
|
|
||||||
target_link_libraries(my_project continuable)
|
|
||||||
```
|
|
||||||
|
|
||||||
On POSIX platforms you are required to link your application against a corresponding thread library, otherwise `std::future's` won't work properly, this is done automatically by the provided CMake project.
|
|
||||||
|
|
||||||
#### As CMake library
|
|
||||||
|
|
||||||
Additionally the project exports a `continuable` target which is importable through CMake when installed:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
cmake --build . --target INSTALL --config Release
|
|
||||||
```
|
|
||||||
|
|
||||||
`CMakeLists.txt`:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
find_package(continuable REQUIRED)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building the unit-tests
|
|
||||||
|
|
||||||
In order to build the unit tests clone the repository recursively with all submodules:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Shell:
|
|
||||||
git clone --recursive https://github.com/Naios/continuable.git
|
|
||||||
```
|
|
||||||
## Stability and version
|
|
||||||
|
|
||||||
The library follows the rules of [semantic versioning](http://semver.org/), the API is kept stable across minor versions.
|
|
||||||
|
|
||||||
The CI driven unit-tests are observed through the Clang sanitizers (asan, ubsan and lsan - when compiling with Clang) or Valgrind (when compiling with GCC).
|
|
||||||
|
|
||||||
## Quick reference
|
|
||||||
|
|
||||||
This chapter only overflies the functionality of the continuable library, the full documentation is located at https://naios.github.io/continuable/.
|
|
||||||
|
|
||||||
### Creating Continuables
|
|
||||||
|
|
||||||
Create a continuable from a promise taking function:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
// ...
|
|
||||||
|
|
||||||
auto void_continuable = cti::make_continuable<void>([](auto&& promise) {
|
|
||||||
// ^^^^
|
|
||||||
|
|
||||||
// Resolve the promise later when you have finished your work
|
|
||||||
promise.set_value();
|
|
||||||
});
|
|
||||||
|
|
||||||
auto str_continuable = cti::make_continuable<std::string>([](auto&& promise) {
|
|
||||||
// ^^^^^^^^^^^
|
|
||||||
promise.set_value("Hello, World!");
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Chaining Continuables
|
|
||||||
|
|
||||||
Chain continuables together in order to build up an asynchronous call hierarchy:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
mysql_query("SELECT `id`, `name` FROM `users`")
|
|
||||||
.then([](ResultSet users) {
|
|
||||||
// Return the next continuable to process ...
|
|
||||||
return mysql_query("SELECT `id` name FROM `sessions`");
|
|
||||||
})
|
|
||||||
.then([](ResultSet sessions) {
|
|
||||||
// ... or pass multiple values to the next callback using tuples or pairs ...
|
|
||||||
return std::make_tuple(std::move(sessions), true);
|
|
||||||
})
|
|
||||||
.then([](ResultSet 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([](ResultSet result) {
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:** The continuation chain is invoked when the object is destructed or the `done()` method is called.
|
|
||||||
|
|
||||||
### Providing helper functions
|
|
||||||
|
|
||||||
Returning continuables from helper functions makes chaining simple and expressive:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
// ...
|
|
||||||
|
|
||||||
auto mysql_query(std::string query) {
|
|
||||||
return cti::make_continuable<ResultSet>([query = std::move(query)](auto&& promise) mutable {
|
|
||||||
// Pass the callback to the handler which calls the callback when finished.
|
|
||||||
// Every function accepting callbacks works with continuables.
|
|
||||||
mysql_handle_async_query(std::move(query),
|
|
||||||
std::forward<decltype(promise)>(promise));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// You may use the helper function like you would normally do,
|
|
||||||
// without using the support methods of the continuable.
|
|
||||||
mysql_query("DELETE FROM `users` WHERE `id` = 27361");
|
|
||||||
|
|
||||||
// Or using chaining to handle the result which is covered in the documentation.
|
|
||||||
mysql_query("SELECT `id`, `name` FROM users")
|
|
||||||
.then([](ResultSet result) {
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error handling
|
|
||||||
|
|
||||||
Continuables support asynchronous error handling through exceptions or custom error types.
|
|
||||||
|
|
||||||
The error type will be **`std::exception_ptr`** except if one of the following definition is defined:
|
|
||||||
- **`CONTINUABLE_WITH_CUSTOM_ERROR_TYPE`**: Define this to use a user defined error type.
|
|
||||||
- **`CONTINUABLE_WITH_NO_EXCEPTIONS`**: Define this to use **`std::error_condition`** as error type and to disable exception support. When exceptions are disabled this definition is set automatically.
|
|
||||||
|
|
||||||
Resolving a promise through an error will skip all following result handlers attached through **`then`**:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
auto get_bad_continuable(std::exception const& e) {
|
|
||||||
return cti::make_continuable<void>([=] (auto&& promise) {
|
|
||||||
try {
|
|
||||||
throw e;
|
|
||||||
} catch(...) {
|
|
||||||
promise.set_exception(std::current_exception());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You may handle the exception as following:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
get_bad_continuable()
|
|
||||||
.then([] {
|
|
||||||
// ... never invoked
|
|
||||||
})
|
|
||||||
.then([] {
|
|
||||||
// ... never invoked as well
|
|
||||||
})
|
|
||||||
.fail([] (std::exception_ptr e) {
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(e);
|
|
||||||
} catch(std::exception const& e) {
|
|
||||||
// Handle the exception here
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Connecting Continuables {all, any or sequential}
|
|
||||||
|
|
||||||
Continuables provide the operators **&&** and **||** for logical connection:
|
|
||||||
|
|
||||||
* **&&** invokes the final callback with the compound result of all connected continuables, the continuables were invoked in parallel.
|
|
||||||
* **||** invokes the final callback once with the first result which becomes available.
|
|
||||||
* **>\>** invokes the final callback with the compound result of all connected continuables but the continuations were invokes sequentially.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
auto http_request(std::string url) {
|
|
||||||
return cti::make_continuable<std::string>([](auto&& promise) {
|
|
||||||
promise.set_value("<html>...</html>");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// `all` of connections:
|
|
||||||
(http_request("github.com") && http_request("travis-ci.org") && http_request("atom.io"))
|
|
||||||
.then([](std::string github, std::string travis, std::string atom) {
|
|
||||||
// The callback is called with the response of github, travis and atom.
|
|
||||||
});
|
|
||||||
|
|
||||||
// `any` of connections:
|
|
||||||
(http_request("github.com") || http_request("travis-ci.org") || http_request("atom.io"))
|
|
||||||
.then([](std::string github_or_travis_or_atom) {
|
|
||||||
// The callback is called with the first response of either github, travis or atom.
|
|
||||||
});
|
|
||||||
|
|
||||||
// `sequence` of connections:
|
|
||||||
(http_request("github.com") >> http_request("travis-ci.org") >> http_request("atom.io"))
|
|
||||||
.then([](std::string github, std::string travis, std::string atom) {
|
|
||||||
// The requests are invoked sequentially
|
|
||||||
});
|
|
||||||
|
|
||||||
// mixed logical connections:
|
|
||||||
(http_request("github.com") && (http_request("travis-ci.org") || http_request("atom.io")))
|
|
||||||
.then([](std::string github, std::string travis_or_atom) {
|
|
||||||
// The callback is called with the response of github for sure
|
|
||||||
// and the second parameter represents the response of travis or atom.
|
|
||||||
});
|
|
||||||
|
|
||||||
// There are helper functions for connecting continuables:
|
|
||||||
auto all = cti::when_all(http_request("github.com"), http_request("travis-ci.org"));
|
|
||||||
auto any = cti::when_any(http_request("github.com"), http_request("travis-ci.org"));
|
|
||||||
auto seq = cti::when_seq(http_request("github.com"), http_request("travis-ci.org"));
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:** Logical connections are ensured to be **thread-safe** and **wait-free** by library design (when assuming that *std::call_once* is wait-free - which depends on the toolchain).
|
|
||||||
|
|
||||||
### Partial argument application
|
|
||||||
|
|
||||||
The callback is called only with the arguments it's accepting:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
(http_request("github.com") && read_file("entries.csv"))
|
|
||||||
.then([] {
|
|
||||||
// ^^^^^^ The original signature was <std::string, Buffer>,
|
|
||||||
// however, the callback is only invoked with the amount of
|
|
||||||
// arguments it's accepting.
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dispatching callbacks through a specific executor
|
|
||||||
|
|
||||||
Dispatching a callback through a specific executor is supported through through the second argument of `then()`:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
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);
|
|
||||||
// ^^^^^^^^
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type erasure
|
|
||||||
|
|
||||||
The library was designed in order to avoid type-erasure until really needed. Thus we provide traits to create an alias to a continuable using the **type-erasure backend of your choice**. All templated functors providing a call operator may be used as a backend (*std::function* for instance).
|
|
||||||
|
|
||||||
The library provides aliases for using my [function2 library](https://github.com/Naios/function2) as backend which provides efficient and qualifier correct function wrappers for copyable and non-copyable objects.
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include <continuable/continuable.hpp>
|
|
||||||
|
|
||||||
cti::unique_continuable<int, std::string> unique =
|
|
||||||
cti::make_continuable([value = std::make_unique<int>(0)](auto&& promise) {
|
|
||||||
|
|
||||||
// The use of non copyable objects is possible by design if
|
|
||||||
// the type erasure backend supports it.
|
|
||||||
promise.set_value(*value, "Hello, World!");
|
|
||||||
});
|
|
||||||
|
|
||||||
std::move(unique).then([](int i) {
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
We could also think about using `std::future` as backend but this is even worse then using `std::function` because usually there is, even more, type erasure and allocations involved.
|
|
||||||
Additionally `std::function` doesn't provide support for multiple function overloads
|
|
||||||
|
|
||||||
### Coroutines
|
|
||||||
|
|
||||||
Since version 2.0.0 coroutines (`co_await` and `co_return`) are supported by continuables 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.
|
|
||||||
|
|
||||||
```c++
|
|
||||||
int i = co_await cti::make_continuable<int>([](auto&& promise) {
|
|
||||||
promise.set_value(0);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Future conversion
|
|
||||||
|
|
||||||
The library is capable of converting (*futurizing*) every continuable into a fitting **std::future** through the `continuable<...>::futurize()` method.:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
std::future<std::string> future = http_request("github.com")
|
|
||||||
.then([](std::string response) {
|
|
||||||
// Do sth...
|
|
||||||
return http_request("travis-ci.org") || http_request("atom.io");
|
|
||||||
})
|
|
||||||
.apply(cti::transforms::futurize());
|
|
||||||
// ^^^^^^^^
|
|
||||||
|
|
||||||
std::future<std::tuple<std::string, std::string>> future =
|
|
||||||
(http_request("travis-ci.org") && http_request("atom.io"))
|
|
||||||
.apply(cti::transforms::futurize());
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:** See the [doxygen documentation](https://naios.github.io/continuable/) for detailed information about the return type of `futurize()`.
|
|
||||||
|
|
||||||
## Compatibility
|
|
||||||
|
|
||||||
Tested & compatible with:
|
|
||||||
|
|
||||||
- Visual Studio 2017+ Update 2
|
|
||||||
- Clang 5.0+
|
|
||||||
- GCC 6.0+
|
|
||||||
|
|
||||||
Although the build is observed with the latest toolchains earlier ones might work.
|
|
||||||
|
|
||||||
The library only depends on the standard library when using the `continuable/continuable-base.hpp` header, which provides the basic continuation logic.
|
|
||||||
|
|
||||||
> **Note:** On Posix: don't forget to **link a corresponding thread library** into your application otherwise `std::future's` won't work `(-pthread)` when using future based transforms.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The continuable library is licensed under the MIT License:
|
|
||||||
|
|
||||||
```
|
|
||||||
/**
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v2.0.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
```
|
|
||||||
|
|
||||||
|
Issues 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 changing the implementation or when using the library.
|
||||||
|
|||||||
@ -38,12 +38,12 @@ namespace cti {
|
|||||||
\link continuable_base::operator>> >>\endlink as well as free functions
|
\link continuable_base::operator>> >>\endlink as well as free functions
|
||||||
\ref when_all, \ref when_any and \ref when_seq.
|
\ref when_all, \ref when_any and \ref when_seq.
|
||||||
- asynchronous \link continuable_base::fail error handling\endlink through
|
- asynchronous \link continuable_base::fail error handling\endlink through
|
||||||
\link promise_base_base::set_exception exceptions\endlink,
|
\link promise_base::set_exception exceptions\endlink,
|
||||||
\link configuration error codes\endlink and
|
\link configuration error codes\endlink and
|
||||||
\link configuration user defined types\endlink.
|
\link configuration user defined types\endlink.
|
||||||
- **syntactic sugar** for instance: **partial invocation**, **tuple unpacking**
|
- **syntactic sugar** for instance: **partial invocation**, **tuple unpacking**,
|
||||||
and \link continuable_base::then executors\endlink.
|
`co_await` support and \link continuable_base::then executors\endlink.
|
||||||
- **encapsuled from any runtime**, larger framework or executor making
|
- **encapsuled from any runtime**, larger framework or executors makes
|
||||||
it possible to use continuable even in smaller or esoteric usage scenarios.
|
it possible to use continuable even in smaller or esoteric usage scenarios.
|
||||||
|
|
||||||
\section mainpage-getting-started Getting started
|
\section mainpage-getting-started Getting started
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user