diff --git a/doc/index.dox b/doc/index.dox index 0a8a300..b760112 100644 --- a/doc/index.dox +++ b/doc/index.dox @@ -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 diff --git a/doc/installation.dox b/doc/installation.dox index ad65d37..66391b2 100644 --- a/doc/installation.dox +++ b/doc/installation.dox @@ -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. + + */ } diff --git a/doc/tutorial-awaiting-continuables.dox b/doc/tutorial-awaiting-continuables.dox new file mode 100644 index 0000000..10cb9a9 --- /dev/null +++ b/doc/tutorial-awaiting-continuables.dox @@ -0,0 +1,41 @@ +/* + Copyright(c) 2015 - 2018 Denis Blank + + 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([](auto&& promise) { + promise.set_value(0); +}); +\endcode + +*/ +} diff --git a/doc/tutorial-chaining-continuables.dox b/doc/tutorial-chaining-continuables.dox index 0736f20..3d459c4 100644 --- a/doc/tutorial-chaining-continuables.dox +++ b/doc/tutorial-chaining-continuables.dox @@ -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 , + // 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(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( + [url = std::move(url)](auto&& promise) { + std::async([promise = std::forward(promise)] + () mutable { + promise.set_value(" ... "); + }); + }); +} +\endcode + \section tutorial-chaining-continuables-fail Using fail and exceptions Asynchronous exceptions are supported too. Exceptions that were set through diff --git a/doc/tutorial-promisify-continuables.dox b/doc/tutorial-promisify-continuables.dox new file mode 100644 index 0000000..cdb1170 --- /dev/null +++ b/doc/tutorial-promisify-continuables.dox @@ -0,0 +1,74 @@ +/* + Copyright(c) 2015 - 2018 Denis Blank + + 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::from( + [&](auto&&... args) { + resolver_.async_resolve(std::forward(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 + +*/ +} diff --git a/doc/tutorial-transforming-continuables.dox b/doc/tutorial-transforming-continuables.dox new file mode 100644 index 0000000..60aad44 --- /dev/null +++ b/doc/tutorial-transforming-continuables.dox @@ -0,0 +1,75 @@ +/* + Copyright(c) 2015 - 2018 Denis Blank + + 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(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 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> future = + (http_request("travis-ci.org") && http_request("atom.io")) + .apply(cti::transforms::futurize()); +\endcode +*/ +} diff --git a/doc/tutorial.dox b/doc/tutorial.dox index 6f80838..3b82870 100644 --- a/doc/tutorial.dox +++ b/doc/tutorial.dox @@ -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 + */ } diff --git a/include/continuable/continuable-promisify.hpp b/include/continuable/continuable-promisify.hpp index 86b6c29..b6bb1e3 100644 --- a/include/continuable/continuable-promisify.hpp +++ b/include/continuable/continuable-promisify.hpp @@ -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::from_asio( + /// return cti::promisify::from( /// [&](auto&&... args) { /// resolver_.async_resolve(std::forward(args)...); /// }, @@ -81,8 +81,8 @@ public: /// /// \since 3.0.0 template - static auto from_asio(Callable&& callable, Args&&... args) { - return helper::template from( + static auto from(Callable&& callable, Args&&... args) { + return helper::template from( std::forward(callable), std::forward(args)...); } };