/* Copyright(c) 2015 - 2022 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-creating-continuables Creating continuables \brief Explains how to create a \ref continuable_base. \tableofcontents A \ref continuable is an arbitrary instantiation of a \ref continuable_base, it represents the main class of the library and makes it possible to build up an asynchronous call hierarchy. When dealing with continuables we usually don't know its exact type for avoiding expensive type erasure. The \ref continuable_base is convertible to a \ref continuable which represents a specified type of the \ref continuable_base on the cost of a type erasure. \section tutorial-creating-continuables-ready From a value or exception The library provides \ref make_ready_continuable which may be used to create a \ref continuable_base from an arbitrary amount of values: \code{.cpp} auto one = cti::make_ready_continuable(0); cti::continuable three = cti::make_ready_continuable(0, 1.f, '2'); \endcode \note In most situations you will never use \ref make_ready_continuable because the library is capable of working with plain values directly and thus this burdens unnecessary overhead. Additionally a \ref continuable_base which resolves with an exception may be created through \ref make_exceptional_continuable. \code{.cpp} cti::continuable c = cti::make_exceptional_continuable(std::exception{}); \endcode \section tutorial-creating-continuables-promises From a promise taking callable The main function for creating a \ref continuable_base is \ref make_continuable which must be invoked with the types of arguments it resolves to. It accepts a callable object which accepts an arbitrary object (the \ref promise_base). The \ref promise_base is created by the library and then passed to the given callback. This is in contrast to the usage of the standard `std::promise` which is created by the user. The \ref promise_base exposes methods to resolve it through result values or through an exception. Below we implement pseudo `http_request` function which resolves the request asynchronously trough a `std::string`. \code{.cpp} auto http_request(std::string url) { return cti::make_continuable( [url = std::move(url)](auto&& promise) { // Resolve the promise upon completion of the task. promise.set_value(" ... "); // Or promise.set_exception(...); }); } \endcode An alternative would be a \ref continuable_base with a result of zero arguments: \code{.cpp} auto wait_for(std::chrono::milliseconds duration) { return cti::make_continuable([](auto&& promise) { // ^^^^ // Resolve the promise later when the duration is over promise.set_value(); }); \endcode A \ref continuable_base may resolve with an arbitrary count of result values: \code{.cpp} auto resolve_sth() { return cti::make_continuable( [](auto&& promise) { promise.set_value(0, 1, 2.f, '3'); }); \endcode \warning A \ref promise_base is only usable once and thus invalidated after it was resolved! A \ref promise_base always exposes a call operator for resolving it as like when using \ref promise_base::set_value or \ref promise_base::set_exception. See \ref promise_base for details. \note In order to make proper use of a \ref promise_base you should move it around, store it for later use and resolve it when the asynchronous task was finished or rejected. \section tutorial-creating-continuables-invocation The continuable invocation model An asynchronous call hierarchy that is stored inside the \ref continuable_base is executed when its result is requested (lazy evaluation) in contrast to other commonly used implementations such as `std::future` which execute the asynchronous call hierarchy instantly on creation (eager evaluation). The lazy evaluation strategy used by continuables has many benefits over eager evaluation that is used by other common implementations: - prevention of side effects - evasion of race conditions - ensured deterministic behaviour. The asynchronous call hierarchy is started when the \ref continuable_base is destructed or the \ref continuable_base::done method is called. It is possible to disable the automatic start through calling \ref continuable_base::freeze on the corresponding \ref continuable_base. \attention A \ref continuable_base is not designed to be stored permanently, make sure you call \ref continuable_base::freeze before storing it and start the continuation chain later through calling \ref continuable_base::done. */ }