More work on the documentation

This commit is contained in:
Denis Blank 2018-03-11 08:23:42 +01:00
parent 60f40415c3
commit d7c305ad33
8 changed files with 326 additions and 8 deletions

View File

@ -49,7 +49,7 @@ namespace cti {
\section mainpage-getting-started Getting started
Continuable is a header-only library with zero compilation dependencies.
The \ref installation is explained in its own chapter.
The \ref installation and \ref configuration are explained in its own chapter.
The \ref tutorial is everything you need in order to get to know the libraries
API. Beside of this, there is a detailed in-source documentation provided.
@ -87,7 +87,7 @@ Continuable is licensed under the MIT license:
>
> 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
> 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

View File

@ -26,5 +26,76 @@ namespace cti {
\tableofcontents
## Installation
### How-to use
As mentioned earlier the library is header-only. There is a cmake project provided for simple setup:
#### As git submodule
\endcodesh
# Shell:
git submodule add https://github.com/Naios/continuable.git
\endcode
\endcodecmake
# 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)
\endcode
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:
\endcodesh
mkdir build
cd build
cmake ..
cmake --build . --target INSTALL --config Release
\endcode
`CMakeLists.txt`:
\endcodecmake
find_package(continuable REQUIRED)
\endcode
### Building the unit-tests
In order to build the unit tests clone the repository recursively with all submodules:
\endcodesh
# Shell:
git clone --recursive https://github.com/Naios/continuable.git
\endcode
## 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).
## 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.
*/
}

View File

@ -0,0 +1,41 @@
/*
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.
*/
namespace cti {
/** \page tutorial-awaiting-continuables Awaiting continuables
\brief Explains how to use the \ref continuable_base together with `co_await`.
\tableofcontents
### 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.
\endcodec++
int i = co_await cti::make_continuable<int>([](auto&& promise) {
promise.set_value(0);
});
\endcode
*/
}

View File

@ -69,6 +69,59 @@ mysql_query("SELECT `id`, `name` FROM `users`")
});
\endcode
\subsection tutorial-chaining-continuables-then-partial Making use of partial argument application
Callbacks passed to \link continuable_base::then then \endlink are only called
with the amount of arguments that are accepted.
\code{.cpp}
(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.
});
\endcode
This makes it possible to attach a callback accepting nothing to every
\ref continuable_base.
\subsection tutorial-chaining-continuables-then-executors Assigning a specific executor to then
Dispatching a callback through a specific executor is a common usage scenario and supported through the second argument of \link continuable_base::then then\endlink:
\code{.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);
// ^^^^^^^^
\endcode
The supplied `work` callable may be stored and moved for later usage
on a possible different thread or execution context.
\note If you are intending to change the context the asynchronous task is
running, you need to specify this inside the function that
supplies the \ref continuable_base through moving the \ref promise_base.
\code{.cpp}
auto http_request(std::string url) {
return cti::make_continuable<std::string>(
[url = std::move(url)](auto&& promise) {
std::async([promise = std::forward<decltype(promise)>(promise)]
() mutable {
promise.set_value("<html> ... </html>");
});
});
}
\endcode
\section tutorial-chaining-continuables-fail Using fail and exceptions
Asynchronous exceptions are supported too. Exceptions that were set through

View File

@ -0,0 +1,74 @@
/*
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.
*/
namespace cti {
/** \page tutorial-promisify-continuables Promisify functions
\brief Explains how to promisify callback taking functions into a \ref continuable_base.
\tableofcontents
\section tutorial-promisify-continuables-promisify Promisification and continuables
The promisification has a longer history in the JavaScript world where
the legacy way of asynchronous programming was the usage of callbacks of the
form \code{.js}function(error, result...)\endcode. The ideal way of dealing
with such an asynchronous result is to return a promise and soon utility
helpers were provided to do so.
The usage of callbacks to represent an asynchronous result is still a popular
way nowadays. Thus the library provides the \ref promisify helper class
which makes it possible to convert callback taking functions of various styles
into one that returns a \ref continuable_base instead.
\note Providing promisified APIs for other popular libraries is out of
scope for this library. However contributions are highly welcome to
add more conversion helpers for other commonly used callback styles.
\section tutorial-promisify-continuables-boost Promisify boost::asio
The default callback style is something like
\code{.js}function(error, result...)\endcode as described above.
Continuable offers the \ref promisify::from method for such callback styles.
See an example of how to promisify boost asio's `async_resolve` below:
\code{.cpp}
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));
}
\endcode
Then it should be possible to use `asio::async_resolve` like this:
\code{.cpp}
async_resolve("127.0.0.1", "daytime")
.then([](udp::resolver::iterator iterator) {
// ...
});
\endcode
*/
}

View File

@ -0,0 +1,75 @@
/*
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.
*/
namespace cti {
/** \page tutorial-transforming-continuables Transforming continuables
\brief Explains the conversion into other types such as `std::future`.
\tableofcontents
\section tutorial-transforming-continuables-transforms Transforms in general
Sometimes it's required to change a \ref continuable_base object by its whole.
Thus the library offers the ability to apply a transformation to any
\ref continuable_base through using \link continuable_base::apply apply \endlink
or \link continuable_base::operator | its operator | \endlink.
A transformation accepts a \ref continuable_base and returns
an arbitrary object.
To create a transformation use the \ref make_transform function:
\code{.cpp}
auto transform = cti::make_transform([] (auto&& continuable) {
// Change the continuable
return std::forward<decltype(continuable)>(continuable);
});
\endcode
The library provides several transforms already as part of the
\ref cti::transforms namespace.
\section tutorial-transforming-continuables-future Conversion into std::future
The library is capable of converting (*futurizing*) every continuable into a
fitting `std::future` through the \ref transforms::futurize transform:
\code{.cpp}
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());
// ^^^^^^^^
\endcode
Multiple arguments which can't be handled by `std::future` itself are
converted into `std::tuple`, see \ref transforms::futurize for details.
\code{.cpp}
std::future<std::tuple<std::string, std::string>> future =
(http_request("travis-ci.org") && http_request("atom.io"))
.apply(cti::transforms::futurize());
\endcode
*/
}

View File

@ -33,5 +33,9 @@ This tutorial is split across multiple chapters which should be read in order:
- \subpage tutorial-creating-continuables --- \copybrief tutorial-creating-continuables
- \subpage tutorial-chaining-continuables --- \copybrief tutorial-chaining-continuables
- \subpage tutorial-connecting-continuables --- \copybrief tutorial-connecting-continuables
- \subpage tutorial-transforming-continuables --- \copybrief tutorial-transforming-continuables
- \subpage tutorial-awaiting-continuables --- \copybrief tutorial-awaiting-continuables
- \subpage tutorial-promisify-continuables --- \copybrief tutorial-promisify-continuables
*/
}

View File

@ -44,9 +44,9 @@ namespace cti {
/// Helper class for converting callback taking callable types into a
/// a continuable. Various styles are supported.
/// - `from_asio`: Converts callback taking callable types into continuables
/// which pass an error code as first parameter and the rest of
/// the result afterwards.
/// - `from`: Converts callback taking callable types into continuables
/// which pass an error code as first parameter and the rest of
/// the result afterwards.
///
/// \tparam Result The result of the converted continuable, this should align
/// with the arguments that are passed to the callback.
@ -64,7 +64,7 @@ public:
/// See an example of how to promisify boost asio's async_resolve below:
/// ```cpp
/// auto async_resolve(std::string host, std::string service) {
/// return cti::promisify<asio::ip::udp::resolver::iterator>::from_asio(
/// return cti::promisify<asio::ip::udp::resolver::iterator>::from(
/// [&](auto&&... args) {
/// resolver_.async_resolve(std::forward<decltype(args)>(args)...);
/// },
@ -81,8 +81,8 @@ public:
///
/// \since 3.0.0
template <typename Callable, typename... Args>
static auto from_asio(Callable&& callable, Args&&... args) {
return helper::template from<detail::convert::promisify_asio>(
static auto from(Callable&& callable, Args&&... args) {
return helper::template from<detail::convert::promisify_default>(
std::forward<Callable>(callable), std::forward<Args>(args)...);
}
};