mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Use new types instead of aliases for type erasures
* Makes compiler output much more readable This is configurateable through CONTINUABLE_WITH_IMMEDIATE_TYPES, and automatically enabled for debug builds but disabled for release builds. * Remove the old continuable-trait.hpp header * Make the signature of continuable not dependent anymore on any size of the arguments which fixes the compilation with forward declared types. Thanks Rogiel for the correspoding bug report. Closes #11
This commit is contained in:
parent
2d5aa36b67
commit
c066940d8d
@ -20,6 +20,7 @@ matrix:
|
|||||||
- ninja-build
|
- ninja-build
|
||||||
env:
|
env:
|
||||||
- COMPILER=g++-6
|
- COMPILER=g++-6
|
||||||
|
- BUILD_CONFIG=Debug
|
||||||
- WITH_NO_EXCEPTIONS=OFF
|
- WITH_NO_EXCEPTIONS=OFF
|
||||||
- WITH_AWAIT=OFF
|
- WITH_AWAIT=OFF
|
||||||
- WITH_LIGHT_TESTS=ON
|
- WITH_LIGHT_TESTS=ON
|
||||||
@ -36,6 +37,7 @@ matrix:
|
|||||||
- ninja-build
|
- ninja-build
|
||||||
env:
|
env:
|
||||||
- COMPILER=clang++-5.0
|
- COMPILER=clang++-5.0
|
||||||
|
- BUILD_CONFIG=Release
|
||||||
- WITH_NO_EXCEPTIONS=OFF
|
- WITH_NO_EXCEPTIONS=OFF
|
||||||
- WITH_AWAIT=OFF
|
- WITH_AWAIT=OFF
|
||||||
- WITH_LIGHT_TESTS=OFF
|
- WITH_LIGHT_TESTS=OFF
|
||||||
@ -52,6 +54,7 @@ matrix:
|
|||||||
- ninja-build
|
- ninja-build
|
||||||
env:
|
env:
|
||||||
- COMPILER=clang++-5.0
|
- COMPILER=clang++-5.0
|
||||||
|
- BUILD_CONFIG=Debug
|
||||||
- WITH_NO_EXCEPTIONS=ON
|
- WITH_NO_EXCEPTIONS=ON
|
||||||
- WITH_AWAIT=ON
|
- WITH_AWAIT=ON
|
||||||
- WITH_LIGHT_TESTS=ON
|
- WITH_LIGHT_TESTS=ON
|
||||||
|
|||||||
@ -3,11 +3,14 @@ image:
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- WITH_NO_EXCEPTIONS: OFF
|
- CONFIGURATION: Debug
|
||||||
|
WITH_NO_EXCEPTIONS: OFF
|
||||||
WITH_CPP_LATEST: OFF
|
WITH_CPP_LATEST: OFF
|
||||||
- WITH_NO_EXCEPTIONS: ON
|
- CONFIGURATION: Debug
|
||||||
|
WITH_NO_EXCEPTIONS: ON
|
||||||
WITH_CPP_LATEST: OFF
|
WITH_CPP_LATEST: OFF
|
||||||
- WITH_NO_EXCEPTIONS: OFF
|
- CONFIGURATION: Release
|
||||||
|
WITH_NO_EXCEPTIONS: OFF
|
||||||
WITH_CPP_LATEST: ON
|
WITH_CPP_LATEST: ON
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
|
|||||||
@ -38,13 +38,13 @@ PROJECT_NAME = Continuable
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 3.0.0
|
PROJECT_NUMBER = 4.0.0
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
# quick idea about the purpose of the project. Keep the description short.
|
# quick idea about the purpose of the project. Keep the description short.
|
||||||
|
|
||||||
PROJECT_BRIEF =
|
PROJECT_BRIEF = "C++14 asynchronous allocation aware futures"
|
||||||
|
|
||||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||||
# in the documentation. The maximum height of the logo should not exceed 55
|
# in the documentation. The maximum height of the logo should not exceed 55
|
||||||
|
|||||||
@ -41,7 +41,7 @@ New helper functions were added to create ready continuables:
|
|||||||
|
|
||||||
The implementation of connections were rewritten entirely.
|
The implementation of connections were rewritten entirely.
|
||||||
It is possible now to connect runtime sized containers as well as
|
It is possible now to connect runtime sized containers as well as
|
||||||
deeply nested sequences. See \ref tutorial-connections for details.
|
deeply nested sequences. See \ref tutorial-connecting-continuables for details.
|
||||||
|
|
||||||
Additionally connection overloads were added that accept two iterators
|
Additionally connection overloads were added that accept two iterators
|
||||||
in order to come closer to the interface of the standard library.
|
in order to come closer to the interface of the standard library.
|
||||||
|
|||||||
@ -34,6 +34,7 @@ in order to change the libraries behaviour:
|
|||||||
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
||||||
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
|
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
|
||||||
| `CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK` | Allows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers. |
|
| `CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK` | Allows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers. |
|
||||||
|
| `CONTINUABLE_WITH_IMMEDIATE_TYPES` | Don't decorate the used type erasure, which is done to keep type names minimal for better error messages in debug builds. |
|
||||||
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
|
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -123,19 +123,31 @@ public:
|
|||||||
std::enable_if_t<detail::base::can_accept_continuation<
|
std::enable_if_t<detail::base::can_accept_continuation<
|
||||||
Data, Annotation,
|
Data, Annotation,
|
||||||
detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
|
detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
|
||||||
continuable_base(OtherData&& data)
|
/* implicit */ continuable_base(OtherData&& data)
|
||||||
: data_(detail::base::proxy_continuable<
|
: data_(detail::base::proxy_continuable<
|
||||||
Annotation, detail::traits::unrefcv_t<OtherData>>(
|
Annotation, detail::traits::unrefcv_t<OtherData>>(
|
||||||
std::forward<OtherData>(data))) {
|
std::forward<OtherData>(data))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructor taking the data of other continuable_base objects
|
||||||
|
/// while erasing the hint.
|
||||||
|
///
|
||||||
|
/// This constructor makes it possible to replace the internal data object of
|
||||||
|
/// the continuable by any object which is useful for type-erasure.
|
||||||
|
/*template <typename OData,
|
||||||
|
std::enable_if_t<std::is_convertible<
|
||||||
|
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
||||||
|
continuable_base(continuable_base<OData, Annotation>&& other)
|
||||||
|
: continuable_base(std::move(other).consume()) {
|
||||||
|
}*/
|
||||||
|
|
||||||
/// Constructor taking the data of other continuable_base objects
|
/// Constructor taking the data of other continuable_base objects
|
||||||
/// while erasing the hint.
|
/// while erasing the hint.
|
||||||
///
|
///
|
||||||
/// This constructor makes it possible to replace the internal data object of
|
/// This constructor makes it possible to replace the internal data object of
|
||||||
/// the continuable by any object which is useful for type-erasure.
|
/// the continuable by any object which is useful for type-erasure.
|
||||||
template <typename OData, typename OAnnotation>
|
template <typename OData, typename OAnnotation>
|
||||||
continuable_base(continuable_base<OData, OAnnotation>&& other)
|
/* implicit */ continuable_base(continuable_base<OData, OAnnotation>&& other)
|
||||||
: continuable_base(std::move(other).finish().consume()) {
|
: continuable_base(std::move(other).finish().consume()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,7 +865,7 @@ constexpr auto make_continuable(Continuation&& continuation) {
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto make_ready_continuable(Args&&... args) {
|
auto make_ready_continuable(Args&&... args) {
|
||||||
using detail::base::ready_continuation;
|
using detail::base::ready_continuation;
|
||||||
using detail::traits::identity;
|
using detail::identity;
|
||||||
using detail::traits::unrefcv_t;
|
using detail::traits::unrefcv_t;
|
||||||
return detail::base::attorney::create_from_raw(
|
return detail::base::attorney::create_from_raw(
|
||||||
ready_continuation<unrefcv_t<Args>...>{std::forward<Args>(args)...},
|
ready_continuation<unrefcv_t<Args>...>{std::forward<Args>(args)...},
|
||||||
@ -932,7 +944,7 @@ auto make_cancelling_continuable() {
|
|||||||
/// // Recovered from the failure
|
/// // Recovered from the failure
|
||||||
/// })
|
/// })
|
||||||
/// ```
|
/// ```
|
||||||
/// A corresponding \ref result is returned by \ref recover:
|
/// A corresponding \ref result is returned by \ref recover
|
||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// http_request("example.com")
|
/// http_request("example.com")
|
||||||
/// .then([](std::string content) -> cti::result<int, int> {
|
/// .then([](std::string content) -> cti::result<int, int> {
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace std {
|
|||||||
namespace experimental {
|
namespace experimental {
|
||||||
template <typename Data, typename... Args, typename... FunctionArgs>
|
template <typename Data, typename... Args, typename... FunctionArgs>
|
||||||
struct coroutine_traits<
|
struct coroutine_traits<
|
||||||
cti::continuable_base<Data, cti::detail::traits::identity<Args...>>,
|
cti::continuable_base<Data, cti::detail::identity<Args...>>,
|
||||||
FunctionArgs...> {
|
FunctionArgs...> {
|
||||||
|
|
||||||
using promise_type =
|
using promise_type =
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
||||||
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/core/types.hpp>
|
||||||
|
#include <continuable/detail/utility/identity.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Primitives Primitives
|
/// \defgroup Primitives Primitives
|
||||||
@ -50,12 +51,19 @@ namespace cti {
|
|||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// template<typename... Args>
|
/// template<typename... Args>
|
||||||
/// struct callback {
|
/// struct callback {
|
||||||
/// void operator() (Args...);
|
/// void operator() (Args...) &&;
|
||||||
/// void operator() (cti::exception_arg_t, cti::exception_t);
|
/// void operator() (cti::exception_arg_t, cti::exception_t) &&;
|
||||||
/// };
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
/// \{
|
/// \{
|
||||||
|
|
||||||
|
/// Represents the tag type that is used to specify the signature hint
|
||||||
|
/// of a continuable_base or promise_base.
|
||||||
|
///
|
||||||
|
/// \since 4.0.0
|
||||||
|
template <typename... Args>
|
||||||
|
using signature_arg_t = detail::identity<Args...>;
|
||||||
|
|
||||||
/// Represents the tag type that is used to query the continuation
|
/// Represents the tag type that is used to query the continuation
|
||||||
/// for whether it resolves the callback instantly with its arguments
|
/// for whether it resolves the callback instantly with its arguments
|
||||||
/// without having side effects.
|
/// without having side effects.
|
||||||
@ -69,7 +77,7 @@ struct is_ready_arg_t {};
|
|||||||
/// It's required that the query of is_ready_arg_t returns true.
|
/// It's required that the query of is_ready_arg_t returns true.
|
||||||
///
|
///
|
||||||
/// \since 4.0.0
|
/// \since 4.0.0
|
||||||
struct query_arg_t {};
|
struct query_arg_t { };
|
||||||
|
|
||||||
/// Represents the tag type that is used to disambiguate the
|
/// Represents the tag type that is used to disambiguate the
|
||||||
/// callback operator() in order to take the exception asynchronous chain.
|
/// callback operator() in order to take the exception asynchronous chain.
|
||||||
@ -87,7 +95,7 @@ struct exception_arg_t {};
|
|||||||
///
|
///
|
||||||
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
|
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
|
||||||
"be removed in a later major version!")]] //
|
"be removed in a later major version!")]] //
|
||||||
typedef exception_arg_t dispatch_error_tag;
|
typedef exception_arg_t dispatch_error_tag;
|
||||||
|
|
||||||
/// Represents the type that is used as exception type
|
/// Represents the type that is used as exception type
|
||||||
///
|
///
|
||||||
@ -108,7 +116,7 @@ using exception_t = detail::types::exception_t;
|
|||||||
///
|
///
|
||||||
[[deprecated("The error_type was replaced by exception_t and will "
|
[[deprecated("The error_type was replaced by exception_t and will "
|
||||||
"be removed in a later major version!")]] //
|
"be removed in a later major version!")]] //
|
||||||
typedef exception_t error_type;
|
typedef exception_t error_type;
|
||||||
/// \}
|
/// \}
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
#include <continuable/continuable-primitives.hpp>
|
#include <continuable/continuable-primitives.hpp>
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
#include <continuable/detail/core/annotation.hpp>
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/core/types.hpp>
|
||||||
|
#include <continuable/detail/utility/traits.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
#include <continuable/detail/utility/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
@ -62,7 +63,7 @@ class promise_base
|
|||||||
/// \cond false
|
/// \cond false
|
||||||
;
|
;
|
||||||
template <typename Data, typename... Args>
|
template <typename Data, typename... Args>
|
||||||
class promise_base<Data, detail::traits::identity<Args...>>
|
class promise_base<Data, detail::identity<Args...>>
|
||||||
: detail::util::non_copyable
|
: detail::util::non_copyable
|
||||||
/// \endcond
|
/// \endcond
|
||||||
{ // clang-format on
|
{ // clang-format on
|
||||||
@ -83,8 +84,9 @@ public:
|
|||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
/// Constructor accepting any object convertible to the data object
|
/// Constructor accepting any object convertible to the data object
|
||||||
template <typename OData, std::enable_if_t<std::is_convertible<
|
template <typename OData,
|
||||||
std::decay_t<OData>, Data>::value>* = nullptr>
|
std::enable_if_t<std::is_convertible<
|
||||||
|
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
||||||
promise_base(OData&& data) : data_(std::forward<OData>(data)) {
|
promise_base(OData&& data) : data_(std::forward<OData>(data)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -158,7 +158,7 @@
|
|||||||
/// \since 1.0.0
|
/// \since 1.0.0
|
||||||
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
||||||
cti::detail::testing::assert_async_types( \
|
cti::detail::testing::assert_async_types( \
|
||||||
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
CONTINUABLE, cti::detail::identity<__VA_ARGS__>{})
|
||||||
|
|
||||||
/// Asserts that the continuable is finished with the given exception
|
/// Asserts that the continuable is finished with the given exception
|
||||||
///
|
///
|
||||||
|
|||||||
@ -1,89 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.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.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_TRAIT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_TRAIT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <tuple>
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-promise-base.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \defgroup Types Types
|
|
||||||
/// provides the \link cti::continuable continuable\endlink and \link
|
|
||||||
/// cti::promise promise\endlink facility for type erasure.
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// Trait to retrieve a continuable_base type with a given type-erasure backend.
|
|
||||||
///
|
|
||||||
/// Every object may me used as type-erasure backend as long as the
|
|
||||||
/// requirements of a `std::function` like wrapper are satisfied.
|
|
||||||
///
|
|
||||||
/// \tparam CallbackWrapper The type which is used to erase the callback.
|
|
||||||
///
|
|
||||||
/// \tparam ContinuationWrapper The type which is used to erase the
|
|
||||||
/// continuation data.
|
|
||||||
///
|
|
||||||
/// \tparam Args The current signature of the continuable.
|
|
||||||
template <template <std::size_t, typename...> class CallbackWrapper,
|
|
||||||
template <std::size_t, typename...> class ContinuationWrapper,
|
|
||||||
typename... Args>
|
|
||||||
class continuable_trait {
|
|
||||||
|
|
||||||
using callback = CallbackWrapper<0U, void(Args...)&&,
|
|
||||||
void(exception_arg_t, exception_t) &&>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// The promise type which is used to resolve continuations
|
|
||||||
using promise = promise_base<callback, detail::traits::identity<Args...>>;
|
|
||||||
|
|
||||||
/// The continuable type for the given parameters.
|
|
||||||
using continuable = continuable_base<
|
|
||||||
ContinuationWrapper<
|
|
||||||
// Size the buffer for the small functor optimization so the
|
|
||||||
// result itself fits in and guarantee that a pointer can
|
|
||||||
// fit in as well.
|
|
||||||
(sizeof(detail::base::ready_continuation<Args...>) < sizeof(void*)
|
|
||||||
? sizeof(void*)
|
|
||||||
: sizeof(detail::base::ready_continuation<Args...>)),
|
|
||||||
void(promise), //
|
|
||||||
bool(is_ready_arg_t) const, //
|
|
||||||
std::tuple<Args...>(query_arg_t) //
|
|
||||||
>,
|
|
||||||
detail::traits::identity<Args...>>;
|
|
||||||
};
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_TRAIT_HPP_INCLUDED
|
|
||||||
@ -31,9 +31,11 @@
|
|||||||
#ifndef CONTINUABLE_TYPES_HPP_INCLUDED
|
#ifndef CONTINUABLE_TYPES_HPP_INCLUDED
|
||||||
#define CONTINUABLE_TYPES_HPP_INCLUDED
|
#define CONTINUABLE_TYPES_HPP_INCLUDED
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <function2/function2.hpp>
|
#include <function2/function2.hpp>
|
||||||
#include <continuable/continuable-trait.hpp>
|
#include <continuable/continuable-base.hpp>
|
||||||
|
#include <continuable/continuable-primitives.hpp>
|
||||||
|
#include <continuable/continuable-promise-base.hpp>
|
||||||
|
#include <continuable/detail/other/erasure.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Types Types
|
/// \defgroup Types Types
|
||||||
@ -41,57 +43,65 @@ namespace cti {
|
|||||||
/// cti::promise promise\endlink facility for type erasure.
|
/// cti::promise promise\endlink facility for type erasure.
|
||||||
/// \{
|
/// \{
|
||||||
|
|
||||||
// clang-format off
|
/// Deduces to the preferred continuation capacity for a possible
|
||||||
namespace detail {
|
/// small functor optimization. The given capacity size is always enough to
|
||||||
/// A function which isn't size adjusted and move only
|
/// to avoid any allocation when storing a ready continuable_base.
|
||||||
template<std::size_t, typename... Args>
|
///
|
||||||
using unique_function_adapter = fu2::unique_function<Args...>;
|
/// \since 4.0.0
|
||||||
/// A function which is size adjusted and move only
|
template <typename... Args>
|
||||||
template<std::size_t Size, typename... Args>
|
using continuation_capacity = detail::erasure::continuation_capacity<Args...>;
|
||||||
using unique_function_adjustable = fu2::function_base<true, false, Size,
|
|
||||||
true, false, Args...>;
|
|
||||||
|
|
||||||
/// We adjust the internal capacity of the outer function wrapper so
|
|
||||||
/// we don't have to allocate twice when using `continuable<...>`.
|
|
||||||
template<typename... Args>
|
|
||||||
using unique_trait_of = continuable_trait<
|
|
||||||
unique_function_adapter,
|
|
||||||
unique_function_adjustable,
|
|
||||||
Args...
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// A type erasure for work objects
|
|
||||||
using work = fu2::unique_function<void()>;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// Defines a non-copyable continuation type which uses the
|
/// Defines a non-copyable continuation type which uses the
|
||||||
/// function2 backend for type erasure.
|
/// function2 backend for type erasure.
|
||||||
///
|
///
|
||||||
/// Usable like: `continuable<int, float>`
|
/// Usable like: `continuable<int, float>`
|
||||||
|
///
|
||||||
|
/// \note You can always define your own continuable with a type erasure of
|
||||||
|
/// choice, the type erasure wrapper just needs to accept a
|
||||||
|
/// callable object with a continuation signature as specified
|
||||||
|
/// in the Primitives section.
|
||||||
|
///
|
||||||
|
/// \since 1.0.0
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using continuable = typename detail::unique_trait_of<
|
using continuable = continuable_base<detail::erasure::continuation<Args...>, //
|
||||||
Args...
|
signature_arg_t<Args...>>;
|
||||||
>::continuable;
|
|
||||||
|
|
||||||
/// Defines a non-copyable promise type which is using the
|
/// Defines a non-copyable promise type which is using the
|
||||||
/// function2 backend for type erasure.
|
/// function2 backend for type erasure.
|
||||||
///
|
///
|
||||||
/// Usable like: `promise<int, float>`
|
/// Usable like: `promise<int, float>`
|
||||||
|
///
|
||||||
|
/// \note You can always define your own promise with a type erasure of
|
||||||
|
/// choice, the type erasure wrapper just needs to accept a
|
||||||
|
/// callable object with a callback signature as specified
|
||||||
|
/// in the Primitives section.
|
||||||
|
///
|
||||||
|
/// \since 1.0.0
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using promise = typename detail::unique_trait_of<
|
using promise = promise_base<detail::erasure::callback<Args...>, //
|
||||||
Args...
|
signature_arg_t<Args...>>;
|
||||||
>::promise;
|
|
||||||
|
|
||||||
/// Defines a non-copyable type erasure which is capable of carrying
|
/// Defines a non-copyable type erasure which is capable of carrying
|
||||||
/// callable objects passed to executors.
|
/// callable objects passed to executors.
|
||||||
///
|
///
|
||||||
|
/// \note You can always define your own work with a type erasure of
|
||||||
|
/// choice, the type erasure wrapper just needs to accept a
|
||||||
|
/// callable object which is callable with a `void()` signature.
|
||||||
|
///
|
||||||
/// \since 4.0.0
|
/// \since 4.0.0
|
||||||
using work = detail::work;
|
class work : public fu2::unique_function<void()> {
|
||||||
|
public:
|
||||||
|
work() = default;
|
||||||
|
~work() = default;
|
||||||
|
work(work const&) = delete;
|
||||||
|
work(work&&) = default;
|
||||||
|
work& operator=(work const&) = delete;
|
||||||
|
work& operator=(work&&) = default;
|
||||||
|
|
||||||
// TODO channel
|
using fu2::unique_function<void()>::unique_function;
|
||||||
// TODO sink
|
using fu2::unique_function<void()>::operator=;
|
||||||
|
using fu2::unique_function<void()>::operator();
|
||||||
// clang-format on
|
};
|
||||||
/// \}
|
/// \}
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,6 @@ namespace cti {}
|
|||||||
#include <continuable/continuable-promise-base.hpp>
|
#include <continuable/continuable-promise-base.hpp>
|
||||||
#include <continuable/continuable-promisify.hpp>
|
#include <continuable/continuable-promisify.hpp>
|
||||||
#include <continuable/continuable-result.hpp>
|
#include <continuable/continuable-result.hpp>
|
||||||
#include <continuable/continuable-trait.hpp>
|
|
||||||
#include <continuable/continuable-transforms.hpp>
|
#include <continuable/continuable-transforms.hpp>
|
||||||
#include <continuable/continuable-traverse-async.hpp>
|
#include <continuable/continuable-traverse-async.hpp>
|
||||||
#include <continuable/continuable-traverse.hpp>
|
#include <continuable/continuable-traverse.hpp>
|
||||||
|
|||||||
@ -75,13 +75,13 @@ T&& unpack_lazy(container::flat_variant<T>&& value) {
|
|||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
class continuable_box;
|
class continuable_box;
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
class continuable_box<continuable_base<Data, traits::identity<>>> {
|
class continuable_box<continuable_base<Data, identity<>>> {
|
||||||
|
|
||||||
continuable_base<Data, traits::identity<>> continuable_;
|
continuable_base<Data, identity<>> continuable_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(
|
explicit continuable_box(
|
||||||
continuable_base<Data, traits::identity<>>&& continuable)
|
continuable_base<Data, identity<>>&& continuable)
|
||||||
: continuable_(std::move(continuable)) {
|
: continuable_(std::move(continuable)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +101,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename Data, typename First>
|
template <typename Data, typename First>
|
||||||
class continuable_box<continuable_base<Data, traits::identity<First>>> {
|
class continuable_box<continuable_base<Data, identity<First>>> {
|
||||||
|
|
||||||
continuable_base<Data, traits::identity<First>> continuable_;
|
continuable_base<Data, identity<First>> continuable_;
|
||||||
lazy_value_t<First> first_;
|
lazy_value_t<First> first_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(
|
explicit continuable_box(
|
||||||
continuable_base<Data, traits::identity<First>>&& continuable)
|
continuable_base<Data, identity<First>>&& continuable)
|
||||||
: continuable_(std::move(continuable)) {
|
: continuable_(std::move(continuable)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,14 +130,14 @@ public:
|
|||||||
};
|
};
|
||||||
template <typename Data, typename First, typename Second, typename... Rest>
|
template <typename Data, typename First, typename Second, typename... Rest>
|
||||||
class continuable_box<
|
class continuable_box<
|
||||||
continuable_base<Data, traits::identity<First, Second, Rest...>>> {
|
continuable_base<Data, identity<First, Second, Rest...>>> {
|
||||||
|
|
||||||
continuable_base<Data, traits::identity<First, Second, Rest...>> continuable_;
|
continuable_base<Data, identity<First, Second, Rest...>> continuable_;
|
||||||
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(
|
explicit continuable_box(
|
||||||
continuable_base<Data, traits::identity<First, Second, Rest...>>&&
|
continuable_base<Data, identity<First, Second, Rest...>>&&
|
||||||
continuable)
|
continuable)
|
||||||
: continuable_(std::move(continuable)) {
|
: continuable_(std::move(continuable)) {
|
||||||
}
|
}
|
||||||
@ -209,12 +209,12 @@ constexpr auto unbox_continuables(Args&&... args) {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename Callback, typename Data>
|
template <typename Callback, typename Data>
|
||||||
constexpr auto finalize_impl(traits::identity<void>, Callback&& callback,
|
constexpr auto finalize_impl(identity<void>, Callback&& callback,
|
||||||
Data&&) {
|
Data&&) {
|
||||||
return std::forward<Callback>(callback)();
|
return std::forward<Callback>(callback)();
|
||||||
}
|
}
|
||||||
template <typename... Args, typename Callback, typename Data>
|
template <typename... Args, typename Callback, typename Data>
|
||||||
constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
constexpr auto finalize_impl(identity<std::tuple<Args...>>,
|
||||||
Callback&& callback, Data&& data) {
|
Callback&& callback, Data&& data) {
|
||||||
// Call the final callback with the cleaned result
|
// Call the final callback with the cleaned result
|
||||||
return traits::unpack(std::forward<Callback>(callback),
|
return traits::unpack(std::forward<Callback>(callback),
|
||||||
@ -223,7 +223,7 @@ constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
|||||||
|
|
||||||
struct hint_mapper {
|
struct hint_mapper {
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr auto operator()(T...) -> traits::identity<T...> {
|
constexpr auto operator()(T...) -> identity<T...> {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -233,7 +233,7 @@ template <typename Callback, typename Data>
|
|||||||
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
||||||
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
||||||
// Guard the final result against void
|
// Guard the final result against void
|
||||||
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
return detail::finalize_impl(identity<std::decay_t<result_t>>{},
|
||||||
std::forward<Callback>(callback),
|
std::forward<Callback>(callback),
|
||||||
std::forward<Data>(data));
|
std::forward<Data>(data));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,30 +88,30 @@ private:
|
|||||||
|
|
||||||
struct result_deducer {
|
struct result_deducer {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce_one(std::false_type, traits::identity<T>) {
|
static auto deduce_one(std::false_type, identity<T>) {
|
||||||
static_assert(traits::fail<T>::value,
|
static_assert(traits::fail<T>::value,
|
||||||
"Non continuable types except tuple like and homogeneous "
|
"Non continuable types except tuple like and homogeneous "
|
||||||
"containers aren't allowed inside an any expression!");
|
"containers aren't allowed inside an any expression!");
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce_one(std::true_type, traits::identity<T> id) {
|
static auto deduce_one(std::true_type, identity<T> id) {
|
||||||
return base::annotation_of(id);
|
return base::annotation_of(id);
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce(traversal::container_category_tag<false, false>,
|
static auto deduce(traversal::container_category_tag<false, false>,
|
||||||
traits::identity<T> id) {
|
identity<T> id) {
|
||||||
return deduce_one<T>(base::is_continuable<T>{}, id);
|
return deduce_one<T>(base::is_continuable<T>{}, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce a homogeneous container
|
/// Deduce a homogeneous container
|
||||||
template <bool IsTupleLike, typename T>
|
template <bool IsTupleLike, typename T>
|
||||||
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
||||||
traits::identity<T>) {
|
identity<T>) {
|
||||||
|
|
||||||
// Deduce the containing type
|
// Deduce the containing type
|
||||||
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
||||||
return deduce(traversal::container_category_of_t<element_t>{},
|
return deduce(traversal::container_category_of_t<element_t>{},
|
||||||
traits::identity<element_t>{});
|
identity<element_t>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename First, typename... T>
|
template <typename First, typename... T>
|
||||||
@ -125,19 +125,19 @@ struct result_deducer {
|
|||||||
|
|
||||||
template <std::size_t... I, typename T>
|
template <std::size_t... I, typename T>
|
||||||
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
||||||
traits::identity<T>) {
|
identity<T>) {
|
||||||
|
|
||||||
return deduce_same_hints(deduce(
|
return deduce_same_hints(deduce(
|
||||||
traversal::container_category_of_t<
|
traversal::container_category_of_t<
|
||||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
||||||
traits::identity<
|
identity<
|
||||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverse tuple like container
|
/// Traverse tuple like container
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce(traversal::container_category_tag<false, true>,
|
static auto deduce(traversal::container_category_tag<false, true>,
|
||||||
traits::identity<T> id) {
|
identity<T> id) {
|
||||||
|
|
||||||
constexpr auto const size = std::tuple_size<T>::value;
|
constexpr auto const size = std::tuple_size<T>::value;
|
||||||
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
||||||
@ -172,7 +172,7 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
|||||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||||
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
||||||
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
||||||
traits::identity<std::decay_t<Connection>>{})){};
|
identity<std::decay_t<Connection>>{})){};
|
||||||
|
|
||||||
return base::attorney::create_from(
|
return base::attorney::create_from(
|
||||||
[connection =
|
[connection =
|
||||||
|
|||||||
@ -42,7 +42,7 @@ struct annotation_trait;
|
|||||||
|
|
||||||
/// Specialization for a present signature hint
|
/// Specialization for a present signature hint
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
struct annotation_trait<traits::identity<Args...>> {
|
struct annotation_trait<identity<Args...>> {
|
||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
static Continuable&& finish(Continuable&& continuable) {
|
static Continuable&& finish(Continuable&& continuable) {
|
||||||
return std::forward<Continuable>(continuable);
|
return std::forward<Continuable>(continuable);
|
||||||
@ -55,9 +55,9 @@ namespace hints {
|
|||||||
///
|
///
|
||||||
/// This is the overload taking an arbitrary amount of args
|
/// This is the overload taking an arbitrary amount of args
|
||||||
template <typename... HintArgs>
|
template <typename... HintArgs>
|
||||||
struct from_args : std::common_type<traits::identity<HintArgs...>> {};
|
struct from_args : std::common_type<identity<HintArgs...>> {};
|
||||||
template <>
|
template <>
|
||||||
struct from_args<void> : std::common_type<traits::identity<>> {};
|
struct from_args<void> : std::common_type<identity<>> {};
|
||||||
} // namespace hints
|
} // namespace hints
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|||||||
@ -122,8 +122,7 @@ struct ready_continuation<> {
|
|||||||
template <typename Hint, typename Continuation>
|
template <typename Hint, typename Continuation>
|
||||||
struct proxy_continuable;
|
struct proxy_continuable;
|
||||||
template <typename... Args, typename Continuation>
|
template <typename... Args, typename Continuation>
|
||||||
struct proxy_continuable<traits::identity<Args...>, Continuation>
|
struct proxy_continuable<identity<Args...>, Continuation> : Continuation {
|
||||||
: Continuation {
|
|
||||||
|
|
||||||
explicit proxy_continuable(Continuation continuation)
|
explicit proxy_continuable(Continuation continuation)
|
||||||
: Continuation(std::move(continuation)) {
|
: Continuation(std::move(continuation)) {
|
||||||
@ -192,9 +191,9 @@ struct attorney {
|
|||||||
|
|
||||||
/// Returns the signature hint of the given continuable
|
/// Returns the signature hint of the given continuable
|
||||||
template <typename Data, typename... Args>
|
template <typename Data, typename... Args>
|
||||||
constexpr traits::identity<Args...>
|
constexpr identity<Args...>
|
||||||
annotation_of(traits::identity<continuable_base<Data, //
|
annotation_of(identity<continuable_base<Data, //
|
||||||
traits::identity<Args...>>>) {
|
identity<Args...>>>) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,30 +274,28 @@ constexpr void invoke_no_except(T&& callable, Args&&... args) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args, typename T>
|
template <typename... Args, typename T>
|
||||||
void invoke_void_no_except(traits::identity<exception_arg_t, Args...>,
|
void invoke_void_no_except(identity<exception_arg_t, Args...>,
|
||||||
T&& /*callable*/) noexcept {
|
T&& /*callable*/) noexcept {
|
||||||
// Don't invoke the next failure handler when being in an exception handler
|
// Don't invoke the next failure handler when being in an exception handler
|
||||||
}
|
}
|
||||||
template <typename... Args, typename T>
|
template <typename... Args, typename T>
|
||||||
void invoke_void_no_except(traits::identity<Args...>, T&& callable) noexcept {
|
void invoke_void_no_except(identity<Args...>, T&& callable) noexcept {
|
||||||
std::forward<T>(callable)();
|
std::forward<T>(callable)();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
constexpr auto make_invoker(T&& invoke, traits::identity<Args...>) {
|
constexpr auto make_invoker(T&& invoke, identity<Args...>) {
|
||||||
return invoker<std::decay_t<T>, traits::identity<Args...>>(
|
return invoker<std::decay_t<T>, identity<Args...>>(std::forward<T>(invoke));
|
||||||
std::forward<T>(invoke));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - continuable<?...> -> result(next_callback);
|
/// - continuable<?...> -> result(next_callback);
|
||||||
template <typename Data, typename Annotation>
|
template <typename Data, typename Annotation>
|
||||||
constexpr auto
|
constexpr auto invoker_of(identity<continuable_base<Data, Annotation>>) {
|
||||||
invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
|
||||||
/// Get the hint of the unwrapped returned continuable
|
/// Get the hint of the unwrapped returned continuable
|
||||||
using Type =
|
using Type =
|
||||||
decltype(std::declval<continuable_base<Data, Annotation>>().finish());
|
decltype(std::declval<continuable_base<Data, Annotation>>().finish());
|
||||||
|
|
||||||
auto constexpr const hint = base::annotation_of(traits::identify<Type>{});
|
auto constexpr const hint = base::annotation_of(identify<Type>{});
|
||||||
|
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
@ -317,7 +314,7 @@ invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
|||||||
|
|
||||||
/// - ? -> next_callback(?)
|
/// - ? -> next_callback(?)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr auto invoker_of(traits::identity<T>) {
|
constexpr auto invoker_of(identity<T>) {
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
@ -329,26 +326,26 @@ constexpr auto invoker_of(traits::identity<T>) {
|
|||||||
std::move(result));
|
std::move(result));
|
||||||
CONTINUABLE_BLOCK_TRY_END
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
},
|
},
|
||||||
traits::identify<T>{});
|
identify<T>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - void -> next_callback()
|
/// - void -> next_callback()
|
||||||
inline auto invoker_of(traits::identity<void>) {
|
inline auto invoker_of(identity<void>) {
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
invoke_callback(std::forward<decltype(callback)>(callback),
|
invoke_callback(std::forward<decltype(callback)>(callback),
|
||||||
std::forward<decltype(args)>(args)...);
|
std::forward<decltype(args)>(args)...);
|
||||||
invoke_void_no_except(
|
invoke_void_no_except(
|
||||||
traits::identity<traits::unrefcv_t<decltype(args)>...>{},
|
identity<traits::unrefcv_t<decltype(args)>...>{},
|
||||||
std::forward<decltype(next_callback)>(next_callback));
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
CONTINUABLE_BLOCK_TRY_END
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
},
|
},
|
||||||
traits::identity<>{});
|
identity<>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - empty_result -> <cancel>
|
/// - empty_result -> <cancel>
|
||||||
inline auto invoker_of(traits::identity<empty_result>) {
|
inline auto invoker_of(identity<empty_result>) {
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
(void)next_callback;
|
(void)next_callback;
|
||||||
@ -362,11 +359,11 @@ inline auto invoker_of(traits::identity<empty_result>) {
|
|||||||
(void)result;
|
(void)result;
|
||||||
CONTINUABLE_BLOCK_TRY_END
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
},
|
},
|
||||||
traits::identity<>{});
|
identity<>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - exceptional_result -> <throw>
|
/// - exceptional_result -> <throw>
|
||||||
inline auto invoker_of(traits::identity<exceptional_result>) {
|
inline auto invoker_of(identity<exceptional_result>) {
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
util::unused(callback, next_callback, args...);
|
util::unused(callback, next_callback, args...);
|
||||||
@ -381,12 +378,12 @@ inline auto invoker_of(traits::identity<exceptional_result>) {
|
|||||||
std::move(result).get_exception());
|
std::move(result).get_exception());
|
||||||
CONTINUABLE_BLOCK_TRY_END
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
},
|
},
|
||||||
traits::identity<>{});
|
identity<>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - result<?...> -> next_callback(?...)
|
/// - result<?...> -> next_callback(?...)
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto invoker_of(traits::identity<result<Args...>>) {
|
auto invoker_of(identity<result<Args...>>) {
|
||||||
return make_invoker(
|
return make_invoker(
|
||||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
@ -416,7 +413,7 @@ auto invoker_of(traits::identity<result<Args...>>) {
|
|||||||
// asynchronous chain.
|
// asynchronous chain.
|
||||||
CONTINUABLE_BLOCK_TRY_END
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
},
|
},
|
||||||
traits::identity<Args...>{});
|
identity<Args...>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a sequenced invoker which is able to invoke
|
/// Returns a sequenced invoker which is able to invoke
|
||||||
@ -443,15 +440,14 @@ inline auto sequenced_unpack_invoker() {
|
|||||||
|
|
||||||
// - std::pair<?, ?> -> next_callback(?, ?)
|
// - std::pair<?, ?> -> next_callback(?, ?)
|
||||||
template <typename First, typename Second>
|
template <typename First, typename Second>
|
||||||
constexpr auto invoker_of(traits::identity<std::pair<First, Second>>) {
|
constexpr auto invoker_of(identity<std::pair<First, Second>>) {
|
||||||
return make_invoker(sequenced_unpack_invoker(),
|
return make_invoker(sequenced_unpack_invoker(), identity<First, Second>{});
|
||||||
traits::identity<First, Second>{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - std::tuple<?...> -> next_callback(?...)
|
// - std::tuple<?...> -> next_callback(?...)
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
constexpr auto invoker_of(traits::identity<std::tuple<Args...>>) {
|
constexpr auto invoker_of(identity<std::tuple<Args...>>) {
|
||||||
return make_invoker(sequenced_unpack_invoker(), traits::identity<Args...>{});
|
return make_invoker(sequenced_unpack_invoker(), identity<Args...>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CONTINUABLE_BLOCK_TRY_BEGIN
|
#undef CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
@ -511,24 +507,20 @@ namespace proto {
|
|||||||
template <handle_results HandleResults, typename Base, typename Hint>
|
template <handle_results HandleResults, typename Base, typename Hint>
|
||||||
struct result_handler_base;
|
struct result_handler_base;
|
||||||
template <typename Base, typename... Args>
|
template <typename Base, typename... Args>
|
||||||
struct result_handler_base<handle_results::no, Base,
|
struct result_handler_base<handle_results::no, Base, identity<Args...>> {
|
||||||
traits::identity<Args...>> {
|
|
||||||
void operator()(Args... args) && {
|
void operator()(Args... args) && {
|
||||||
// Forward the arguments to the next callback
|
// Forward the arguments to the next callback
|
||||||
std::move(static_cast<Base*>(this)->next_callback_)(std::move(args)...);
|
std::move(static_cast<Base*>(this)->next_callback_)(std::move(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename Base, typename... Args>
|
template <typename Base, typename... Args>
|
||||||
struct result_handler_base<handle_results::yes, Base,
|
struct result_handler_base<handle_results::yes, Base, identity<Args...>> {
|
||||||
traits::identity<Args...>> {
|
|
||||||
/// The operator which is called when the result was provided
|
/// The operator which is called when the result was provided
|
||||||
void operator()(Args... args) && {
|
void operator()(Args... args) && {
|
||||||
// In order to retrieve the correct decorator we must know what the
|
// In order to retrieve the correct decorator we must know what the
|
||||||
// result type is.
|
// result type is.
|
||||||
constexpr auto result =
|
constexpr auto result = identify<decltype(decoration::invoke_callback(
|
||||||
traits::identify<decltype(decoration::invoke_callback(
|
std::move(static_cast<Base*>(this)->callback_), std::move(args)...))>{};
|
||||||
std::move(static_cast<Base*>(this)->callback_),
|
|
||||||
std::move(args)...))>{};
|
|
||||||
|
|
||||||
// Pick the correct invoker that handles decorating of the result
|
// Pick the correct invoker that handles decorating of the result
|
||||||
auto invoker = decoration::invoker_of(result);
|
auto invoker = decoration::invoker_of(result);
|
||||||
@ -557,10 +549,9 @@ template <typename Base>
|
|||||||
struct error_handler_base<handle_errors::forward, Base> {
|
struct error_handler_base<handle_errors::forward, Base> {
|
||||||
/// The operator which is called when an error occurred
|
/// The operator which is called when an error occurred
|
||||||
void operator()(exception_arg_t, exception_t exception) && {
|
void operator()(exception_arg_t, exception_t exception) && {
|
||||||
constexpr auto result =
|
constexpr auto result = identify<decltype(decoration::invoke_callback(
|
||||||
traits::identify<decltype(decoration::invoke_callback(
|
std::move(static_cast<Base*>(this)->callback_), exception_arg_t{},
|
||||||
std::move(static_cast<Base*>(this)->callback_), exception_arg_t{},
|
std::move(exception)))>{};
|
||||||
std::move(exception)))>{};
|
|
||||||
|
|
||||||
auto invoker = decoration::invoker_of(result);
|
auto invoker = decoration::invoker_of(result);
|
||||||
|
|
||||||
@ -582,16 +573,16 @@ struct callback_base;
|
|||||||
template <typename... Args, handle_results HandleResults,
|
template <typename... Args, handle_results HandleResults,
|
||||||
handle_errors HandleErrors, typename Callback, typename Executor,
|
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||||
typename NextCallback>
|
typename NextCallback>
|
||||||
struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
struct callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||||
Callback, Executor, NextCallback>
|
Executor, NextCallback>
|
||||||
: proto::result_handler_base<
|
: proto::result_handler_base<
|
||||||
HandleResults,
|
HandleResults,
|
||||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||||
Callback, Executor, NextCallback>,
|
Callback, Executor, NextCallback>,
|
||||||
traits::identity<Args...>>,
|
identity<Args...>>,
|
||||||
proto::error_handler_base<
|
proto::error_handler_base<
|
||||||
HandleErrors,
|
HandleErrors,
|
||||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||||
Callback, Executor, NextCallback>>,
|
Callback, Executor, NextCallback>>,
|
||||||
util::non_copyable {
|
util::non_copyable {
|
||||||
|
|
||||||
@ -608,15 +599,15 @@ struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
|||||||
/// Pull the result handling operator() in
|
/// Pull the result handling operator() in
|
||||||
using proto::result_handler_base<
|
using proto::result_handler_base<
|
||||||
HandleResults,
|
HandleResults,
|
||||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||||
Callback, Executor, NextCallback>,
|
Executor, NextCallback>,
|
||||||
traits::identity<Args...>>::operator();
|
identity<Args...>>::operator();
|
||||||
|
|
||||||
/// Pull the error handling operator() in
|
/// Pull the error handling operator() in
|
||||||
using proto::error_handler_base<
|
using proto::error_handler_base<
|
||||||
HandleErrors,
|
HandleErrors,
|
||||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||||
Callback, Executor, NextCallback>>::operator();
|
Executor, NextCallback>>::operator();
|
||||||
|
|
||||||
/// Resolves the continuation with the given values
|
/// Resolves the continuation with the given values
|
||||||
void set_value(Args... args) {
|
void set_value(Args... args) {
|
||||||
@ -683,21 +674,19 @@ struct final_callback : util::non_copyable {
|
|||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
next_hint_of(std::integral_constant<handle_results, handle_results::yes>,
|
next_hint_of(std::integral_constant<handle_results, handle_results::yes>,
|
||||||
traits::identity<T> /*callback*/,
|
identity<T> /*callback*/, identity<Args...> /*current*/) {
|
||||||
traits::identity<Args...> /*current*/) {
|
|
||||||
// Partial Invoke the given callback
|
// Partial Invoke the given callback
|
||||||
using Result = decltype(
|
using Result = decltype(
|
||||||
decoration::invoke_callback(std::declval<T>(), std::declval<Args>()...));
|
decoration::invoke_callback(std::declval<T>(), std::declval<Args>()...));
|
||||||
|
|
||||||
// Return the hint of thr given invoker
|
// Return the hint of thr given invoker
|
||||||
return decltype(decoration::invoker_of(traits::identify<Result>{}).hint()){};
|
return decltype(decoration::invoker_of(identify<Result>{}).hint()){};
|
||||||
}
|
}
|
||||||
/// Don't progress the hint when we don't continue
|
/// Don't progress the hint when we don't continue
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
|
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
|
||||||
traits::identity<T> /*callback*/,
|
identity<T> /*callback*/, identity<Args...> current) {
|
||||||
traits::identity<Args...> current) {
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,9 +718,9 @@ struct chained_continuation;
|
|||||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||||
handle_errors HandleErrors, typename Continuation, typename Callback,
|
handle_errors HandleErrors, typename Continuation, typename Callback,
|
||||||
typename Executor>
|
typename Executor>
|
||||||
struct chained_continuation<traits::identity<Args...>,
|
struct chained_continuation<identity<Args...>, identity<NextArgs...>,
|
||||||
traits::identity<NextArgs...>, HandleResults,
|
HandleResults, HandleErrors, Continuation, Callback,
|
||||||
HandleErrors, Continuation, Callback, Executor> {
|
Executor> {
|
||||||
|
|
||||||
Continuation continuation_;
|
Continuation continuation_;
|
||||||
Callback callback_;
|
Callback callback_;
|
||||||
@ -760,8 +749,8 @@ struct chained_continuation<traits::identity<Args...>,
|
|||||||
// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||||
// - Callback: [](std::string) { }
|
// - Callback: [](std::string) { }
|
||||||
// - NextCallback: []() { }
|
// - NextCallback: []() { }
|
||||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
auto proxy = callbacks::make_callback<identity<Args...>, HandleResults,
|
||||||
HandleResults, HandleErrors>(
|
HandleErrors>(
|
||||||
std::move(callback_), std::move(executor_),
|
std::move(callback_), std::move(executor_),
|
||||||
std::forward<decltype(next_callback)>(next_callback));
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
|
|
||||||
@ -791,9 +780,9 @@ struct chained_continuation<traits::identity<Args...>,
|
|||||||
// Specialization to unpack ready continuables directly
|
// Specialization to unpack ready continuables directly
|
||||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||||
handle_errors HandleErrors, typename Callback, typename Executor>
|
handle_errors HandleErrors, typename Callback, typename Executor>
|
||||||
struct chained_continuation<
|
struct chained_continuation<identity<Args...>, identity<NextArgs...>,
|
||||||
traits::identity<Args...>, traits::identity<NextArgs...>, HandleResults,
|
HandleResults, HandleErrors,
|
||||||
HandleErrors, ready_continuation<Args...>, Callback, Executor> {
|
ready_continuation<Args...>, Callback, Executor> {
|
||||||
|
|
||||||
ready_continuation<Args...> continuation_;
|
ready_continuation<Args...> continuation_;
|
||||||
Callback callback_;
|
Callback callback_;
|
||||||
@ -814,8 +803,8 @@ struct chained_continuation<
|
|||||||
|
|
||||||
template <typename NextCallback>
|
template <typename NextCallback>
|
||||||
void operator()(NextCallback&& next_callback) {
|
void operator()(NextCallback&& next_callback) {
|
||||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
auto proxy = callbacks::make_callback<identity<Args...>, HandleResults,
|
||||||
HandleResults, HandleErrors>(
|
HandleErrors>(
|
||||||
std::move(callback_), std::move(executor_),
|
std::move(callback_), std::move(executor_),
|
||||||
std::forward<decltype(next_callback)>(next_callback));
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
|
|
||||||
@ -850,10 +839,10 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
|||||||
static_assert(is_continuable<std::decay_t<Continuation>>{},
|
static_assert(is_continuable<std::decay_t<Continuation>>{},
|
||||||
"Expected a continuation!");
|
"Expected a continuation!");
|
||||||
|
|
||||||
using Hint = decltype(base::annotation_of(traits::identify<Continuation>()));
|
using Hint = decltype(base::annotation_of(identify<Continuation>()));
|
||||||
constexpr auto next_hint =
|
constexpr auto next_hint =
|
||||||
next_hint_of(std::integral_constant<handle_results, HandleResults>{},
|
next_hint_of(std::integral_constant<handle_results, HandleResults>{},
|
||||||
traits::identify<decltype(callback)>{}, Hint{});
|
identify<decltype(callback)>{}, Hint{});
|
||||||
|
|
||||||
auto ownership = attorney::ownership_of(continuation);
|
auto ownership = attorney::ownership_of(continuation);
|
||||||
auto data =
|
auto data =
|
||||||
@ -875,7 +864,7 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
|||||||
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||||
template <typename Data, typename... Args>
|
template <typename Data, typename... Args>
|
||||||
void finalize_continuation(
|
void finalize_continuation(
|
||||||
continuable_base<Data, traits::identity<Args...>>&& continuation) noexcept {
|
continuable_base<Data, identity<Args...>>&& continuation) noexcept {
|
||||||
#ifdef CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
|
#ifdef CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
|
||||||
invoke_continuation(std::move(continuation),
|
invoke_continuation(std::move(continuation),
|
||||||
CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK<Args...>{});
|
CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK<Args...>{});
|
||||||
@ -890,13 +879,12 @@ void finalize_continuation(
|
|||||||
template <typename Data, typename Annotation, typename Continuation>
|
template <typename Data, typename Annotation, typename Continuation>
|
||||||
struct can_accept_continuation : std::false_type {};
|
struct can_accept_continuation : std::false_type {};
|
||||||
template <typename Data, typename... Args, typename Continuation>
|
template <typename Data, typename... Args, typename Continuation>
|
||||||
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
|
struct can_accept_continuation<Data, identity<Args...>, Continuation>
|
||||||
: traits::conjunction<
|
: traits::conjunction<
|
||||||
traits::is_invocable<Continuation,
|
traits::is_invocable<Continuation,
|
||||||
callbacks::final_callback<Args...>>,
|
callbacks::final_callback<Args...>>,
|
||||||
std::is_convertible<
|
std::is_convertible<
|
||||||
proxy_continuable<traits::identity<Args...>, Continuation>,
|
proxy_continuable<identity<Args...>, Continuation>, Data>> {};
|
||||||
Data>> {};
|
|
||||||
|
|
||||||
/// Workaround for GCC bug:
|
/// Workaround for GCC bug:
|
||||||
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/utility/identity.hpp>
|
||||||
|
|
||||||
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
|
|||||||
@ -106,6 +106,18 @@
|
|||||||
#else
|
#else
|
||||||
#undef CONTINUABLE_HAS_EXCEPTIONS
|
#undef CONTINUABLE_HAS_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// Define CONTINUABLE_HAS_IMMEDIATE_TYPES when either
|
||||||
|
/// - CONTINUABLE_WITH_IMMEDIATE_TYPES is defined
|
||||||
|
/// - Building in release mode (NDEBUG is defined)
|
||||||
|
///
|
||||||
|
/// Build error messages will become more readable in debug mode while
|
||||||
|
/// we don't suffer any runtime penalty in release.
|
||||||
|
#if defined(CONTINUABLE_WITH_IMMEDIATE_TYPES) || defined(NDEBUG)
|
||||||
|
#define CONTINUABLE_HAS_IMMEDIATE_TYPES 1
|
||||||
|
#else
|
||||||
|
#undef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||||
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED
|
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED
|
||||||
|
|||||||
@ -57,7 +57,7 @@ using std::experimental::coroutine_handle;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct result_from_identity;
|
struct result_from_identity;
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
struct result_from_identity<traits::identity<T...>> {
|
struct result_from_identity<identity<T...>> {
|
||||||
using result_t = result<T...>;
|
using result_t = result<T...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ struct result_from_identity<traits::identity<T...>> {
|
|||||||
/// for waiting on a continuable in a stackless coroutine.
|
/// for waiting on a continuable in a stackless coroutine.
|
||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
class awaitable {
|
class awaitable {
|
||||||
using hint_t = decltype(base::annotation_of(traits::identify<Continuable>{}));
|
using hint_t = decltype(base::annotation_of(identify<Continuable>{}));
|
||||||
using result_t = typename result_from_identity<hint_t>::result_t;
|
using result_t = typename result_from_identity<hint_t>::result_t;
|
||||||
|
|
||||||
/// The continuable which is invoked upon suspension
|
/// The continuable which is invoked upon suspension
|
||||||
|
|||||||
180
include/continuable/detail/other/erasure.hpp
Normal file
180
include/continuable/detail/other/erasure.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v4.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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <function2/function2.hpp>
|
||||||
|
#include <continuable/detail/core/base.hpp>
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/utility/traits.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace erasure {
|
||||||
|
template <typename... Args>
|
||||||
|
using callback_erasure_t =
|
||||||
|
fu2::function_base<true, false, fu2::capacity_none, true, false,
|
||||||
|
void(Args...)&&, void(exception_arg_t, exception_t) &&>;
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||||
|
template <typename... Args>
|
||||||
|
using callback = callback_erasure_t<Args...>;
|
||||||
|
#else
|
||||||
|
template <typename... Args>
|
||||||
|
class callback;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_callback : std::false_type {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct is_callback<callback<Args...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
class callback : public callback_erasure_t<Args...> {
|
||||||
|
public:
|
||||||
|
using erasure_t = callback_erasure_t<Args...>;
|
||||||
|
erasure_t erasure_;
|
||||||
|
|
||||||
|
callback() = default;
|
||||||
|
~callback() = default;
|
||||||
|
callback(callback const&) = delete;
|
||||||
|
callback(callback&&) = default;
|
||||||
|
callback& operator=(callback const&) = delete;
|
||||||
|
callback& operator=(callback&&) = default;
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
||||||
|
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
||||||
|
/* implicit */ callback(T&& callable) : erasure_(std::forward<T>(callable)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
||||||
|
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
||||||
|
callback& operator=(T&& callable) {
|
||||||
|
erasure_ = std::forward<T>(callable);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(Args... args) && {
|
||||||
|
std::move(erasure_)(std::move(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(exception_arg_t exception_arg, exception_t exception) && {
|
||||||
|
std::move(erasure_)(exception_arg, std::move(exception));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
struct continuation_capacity {
|
||||||
|
using type = union {
|
||||||
|
void* pointer_;
|
||||||
|
base::ready_continuation<Args...> continuation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::size_t capacity = sizeof(type);
|
||||||
|
static constexpr std::size_t alignment = alignof(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
using continuation_erasure_t = fu2::function_base<
|
||||||
|
true, false, continuation_capacity<Args...>, true, false,
|
||||||
|
void(promise_base<callback<Args...>, signature_arg_t<Args...>>),
|
||||||
|
bool(is_ready_arg_t) const, std::tuple<Args...>(query_arg_t)>;
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||||
|
template <typename... Args>
|
||||||
|
using continuation = continuation_erasure_t<Args...>;
|
||||||
|
#else
|
||||||
|
template <typename... Args>
|
||||||
|
class continuation;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_continuation : std::false_type {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct is_continuation<continuation<Args...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
class continuation {
|
||||||
|
using erasure_t = continuation_erasure_t<Args...>;
|
||||||
|
erasure_t erasure_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
continuation() = default;
|
||||||
|
~continuation() = default;
|
||||||
|
continuation(continuation const&) = delete;
|
||||||
|
continuation(continuation&&) = default;
|
||||||
|
continuation& operator=(continuation const&) = delete;
|
||||||
|
continuation& operator=(continuation&&) = default;
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
||||||
|
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
||||||
|
nullptr>
|
||||||
|
/* implicit */ continuation(T&& callable)
|
||||||
|
: erasure_(std::forward<T>(callable)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
||||||
|
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
||||||
|
nullptr>
|
||||||
|
continuation& operator=(T&& callable) {
|
||||||
|
erasure_ = std::forward<T>(callable);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(promise_base<callback<Args...>, //
|
||||||
|
signature_arg_t<Args...>>
|
||||||
|
promise) {
|
||||||
|
erasure_(std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(is_ready_arg_t is_ready_arg) const {
|
||||||
|
return erasure_(is_ready_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<Args...> operator()(query_arg_t query_arg) {
|
||||||
|
return erasure_(query_arg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
} // namespace erasure
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||||
@ -179,15 +179,15 @@ template <typename... Expected>
|
|||||||
struct assert_async_types_validator {
|
struct assert_async_types_validator {
|
||||||
template <typename... Actual>
|
template <typename... Actual>
|
||||||
void operator()(Actual...) {
|
void operator()(Actual...) {
|
||||||
static_assert(std::is_same<traits::identity<Actual...>,
|
static_assert(std::is_same<identity<Actual...>,
|
||||||
traits::identity<Expected...>>::value,
|
identity<Expected...>>::value,
|
||||||
"The called arguments don't match with the expected ones!");
|
"The called arguments don't match with the expected ones!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C, typename... Args>
|
template <typename C, typename... Args>
|
||||||
void assert_async_types(C&& continuable,
|
void assert_async_types(C&& continuable,
|
||||||
traits::identity<Args...> /*expected*/) {
|
identity<Args...> /*expected*/) {
|
||||||
assert_async_validation(std::forward<C>(continuable),
|
assert_async_validation(std::forward<C>(continuable),
|
||||||
assert_async_types_validator<Args...>{});
|
assert_async_types_validator<Args...>{});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,7 +77,7 @@ template <typename Hint>
|
|||||||
class promise_callback;
|
class promise_callback;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
class promise_callback<traits::identity<Args...>>
|
class promise_callback<identity<Args...>>
|
||||||
: public future_trait<Args...> {
|
: public future_trait<Args...> {
|
||||||
|
|
||||||
typename future_trait<Args...>::promise_t promise_;
|
typename future_trait<Args...>::promise_t promise_;
|
||||||
@ -119,7 +119,7 @@ template <typename Data, typename Annotation>
|
|||||||
auto as_future(continuable_base<Data, Annotation>&& continuable) {
|
auto as_future(continuable_base<Data, Annotation>&& continuable) {
|
||||||
// Create the promise which is able to supply the current arguments
|
// Create the promise which is able to supply the current arguments
|
||||||
constexpr auto const hint =
|
constexpr auto const hint =
|
||||||
base::annotation_of(traits::identify<decltype(continuable)>{});
|
base::annotation_of(identify<decltype(continuable)>{});
|
||||||
|
|
||||||
promise_callback<std::decay_t<decltype(hint)>> callback;
|
promise_callback<std::decay_t<decltype(hint)>> callback;
|
||||||
(void)hint;
|
(void)hint;
|
||||||
|
|||||||
@ -62,7 +62,7 @@ template <typename T>
|
|||||||
using align_of_helper = std::integral_constant<std::size_t, alignof(T)>;
|
using align_of_helper = std::integral_constant<std::size_t, alignof(T)>;
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr auto storage_of_impl(traits::identity<T...>) {
|
constexpr auto storage_of_impl(identity<T...>) {
|
||||||
constexpr auto size = max_element_of({(size_of_helper<T>::value)...});
|
constexpr auto size = max_element_of({(size_of_helper<T>::value)...});
|
||||||
constexpr auto align = max_element_of({(align_of_helper<T>::value)...});
|
constexpr auto align = max_element_of({(align_of_helper<T>::value)...});
|
||||||
return std::aligned_storage_t<size, align>{};
|
return std::aligned_storage_t<size, align>{};
|
||||||
@ -70,7 +70,7 @@ constexpr auto storage_of_impl(traits::identity<T...>) {
|
|||||||
|
|
||||||
/// Declares the aligned storage union for the given types
|
/// Declares the aligned storage union for the given types
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
using storage_of_t = decltype(storage_of_impl(traits::identity<T...>{}));
|
using storage_of_t = decltype(storage_of_impl(identity<T...>{}));
|
||||||
|
|
||||||
/// The value fpr the empty slot
|
/// The value fpr the empty slot
|
||||||
using slot_t = std::uint8_t;
|
using slot_t = std::uint8_t;
|
||||||
|
|||||||
54
include/continuable/detail/utility/identity.hpp
Normal file
54
include/continuable/detail/utility/identity.hpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v4.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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
/// A tagging type for wrapping other types
|
||||||
|
template <typename... T>
|
||||||
|
struct identity {};
|
||||||
|
|
||||||
|
template <typename>
|
||||||
|
struct is_identity : std::false_type {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct is_identity<identity<Args...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||||
|
identity<std::decay_t<T>>>;
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||||
@ -36,6 +36,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/utility/identity.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -69,19 +70,6 @@ auto make_flat_tuple(T&&... args) {
|
|||||||
return std::tuple<T...>{std::forward<T>(args)...};
|
return std::tuple<T...>{std::forward<T>(args)...};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A tagging type for wrapping other types
|
|
||||||
template <typename... T>
|
|
||||||
struct identity {};
|
|
||||||
|
|
||||||
template <typename>
|
|
||||||
struct is_identity : std::false_type {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct is_identity<identity<Args...>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
|
||||||
identity<std::decay_t<T>>>;
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_CXX17_VOID_T)
|
#if defined(CONTINUABLE_HAS_CXX17_VOID_T)
|
||||||
using std::void_t;
|
using std::void_t;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -17,9 +17,11 @@ target_link_libraries(test-continuable-base
|
|||||||
|
|
||||||
add_executable(test-continuable-single
|
add_executable(test-continuable-single
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-connection-noinst
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-connection-noinst
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-forward-decl.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-flat-variant.cpp
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-flat-variant.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-result.cpp
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-result.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-promisify.cpp
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-promisify.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-erasure.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse.cpp
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse-async.cpp)
|
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse-async.cpp)
|
||||||
|
|
||||||
|
|||||||
@ -134,7 +134,7 @@ TYPED_TEST(single_dimension_tests, are_exceptions_partial_applyable) {
|
|||||||
handled = false;
|
handled = false;
|
||||||
ASSERT_ASYNC_INCOMPLETION(
|
ASSERT_ASYNC_INCOMPLETION(
|
||||||
this->supply_exception(supply_test_exception(),
|
this->supply_exception(supply_test_exception(),
|
||||||
detail::traits::identity<int, int>{})
|
detail::identity<int, int>{})
|
||||||
.fail([&]() -> result<int, int> {
|
.fail([&]() -> result<int, int> {
|
||||||
EXPECT_FALSE(handled);
|
EXPECT_FALSE(handled);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|||||||
89
test/unit-test/single/test-continuable-erasure.cpp
Normal file
89
test/unit-test/single/test-continuable-erasure.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <test-continuable.hpp>
|
||||||
|
|
||||||
|
using namespace cti;
|
||||||
|
|
||||||
|
struct mypromise {
|
||||||
|
void operator()() && {
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(exception_arg_t, exception_t) && {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct my_continuation {
|
||||||
|
template <typename Callback>
|
||||||
|
void operator()(Callback&&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(is_ready_arg_t) const noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<> operator()(query_arg_t) {
|
||||||
|
return std::make_tuple();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(single_erasure_test, is_assignable_from_promise) {
|
||||||
|
detail::erasure::callback<> p(mypromise{});
|
||||||
|
std::move(p)();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(single_erasure_test, is_assignable_from_continuation) {
|
||||||
|
detail::erasure::continuation<> c(my_continuation{});
|
||||||
|
ASSERT_TRUE(c(is_ready_arg_t{}));
|
||||||
|
c(mypromise{});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(single_erasure_test, is_constructible_from_work) {
|
||||||
|
bool flag = false;
|
||||||
|
|
||||||
|
work mywork([&] {
|
||||||
|
EXPECT_FALSE(flag);
|
||||||
|
flag = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_FALSE(flag);
|
||||||
|
mywork();
|
||||||
|
ASSERT_TRUE(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(single_erasure_test, is_assignable_from_work) {
|
||||||
|
bool flag = false;
|
||||||
|
|
||||||
|
work mywork;
|
||||||
|
|
||||||
|
mywork = [&] {
|
||||||
|
EXPECT_FALSE(flag);
|
||||||
|
flag = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ASSERT_FALSE(flag);
|
||||||
|
mywork();
|
||||||
|
ASSERT_TRUE(flag);
|
||||||
|
}
|
||||||
31
test/unit-test/single/test-continuable-forward-decl.cpp
Normal file
31
test/unit-test/single/test-continuable-forward-decl.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <test-continuable.hpp>
|
||||||
|
|
||||||
|
struct forward_decl_type_0;
|
||||||
|
struct forward_decl_type_1;
|
||||||
|
|
||||||
|
cti::continuable<forward_decl_type_0> fails_not_with_forward_decls_1();
|
||||||
|
cti::continuable<forward_decl_type_0, forward_decl_type_1>
|
||||||
|
fails_not_with_forward_decls_2();
|
||||||
@ -34,7 +34,7 @@
|
|||||||
#include <continuable/continuable-testing.hpp>
|
#include <continuable/continuable-testing.hpp>
|
||||||
#include <continuable/continuable.hpp>
|
#include <continuable/continuable.hpp>
|
||||||
|
|
||||||
using cti::detail::traits::identity;
|
using cti::detail::identity;
|
||||||
using cti::detail::util::unused;
|
using cti::detail::util::unused;
|
||||||
|
|
||||||
inline auto to_hint(identity<> /*hint*/) {
|
inline auto to_hint(identity<> /*hint*/) {
|
||||||
@ -48,7 +48,7 @@ auto to_hint(identity<Args...> hint) {
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto supplier_of(Args&&... args) {
|
auto supplier_of(Args&&... args) {
|
||||||
return [values = std::make_tuple(std::forward<Args>(args)...)](
|
return [values = std::make_tuple(std::forward<Args>(args)...)](
|
||||||
auto&& promise) mutable {
|
auto&& promise) mutable {
|
||||||
cti::detail::traits::unpack(
|
cti::detail::traits::unpack(
|
||||||
[&](auto&&... passed) {
|
[&](auto&&... passed) {
|
||||||
promise.set_value(std::forward<decltype(passed)>(passed)...);
|
promise.set_value(std::forward<decltype(passed)>(passed)...);
|
||||||
@ -113,12 +113,12 @@ struct provide_copyable {
|
|||||||
struct provide_unique {
|
struct provide_unique {
|
||||||
template <typename... Args, typename... Hint, typename T>
|
template <typename... Args, typename... Hint, typename T>
|
||||||
auto make(identity<Args...>, identity<Hint...>, T&& callback) {
|
auto make(identity<Args...>, identity<Hint...>, T&& callback) {
|
||||||
return cti::make_continuable<Hint...>(
|
return cti::make_continuable<Hint...>([
|
||||||
[callback = std::forward<T>(callback),
|
callback = std::forward<T>(callback), guard = std::make_unique<int>(0)
|
||||||
guard = std::make_unique<int>(0)](auto&&... args) mutable {
|
](auto&&... args) mutable {
|
||||||
(void)(*guard);
|
(void)(*guard);
|
||||||
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ function renew_build {
|
|||||||
# Configure the project and build it
|
# Configure the project and build it
|
||||||
cmake -GNinja -DCMAKE_CXX_FLAGS="$STD_CXX_FLAGS $CMAKE_CXX_FLAGS -Werror" -DCMAKE_EXE_LINKER_FLAGS="$STD_LINKER_FLAGS" \
|
cmake -GNinja -DCMAKE_CXX_FLAGS="$STD_CXX_FLAGS $CMAKE_CXX_FLAGS -Werror" -DCMAKE_EXE_LINKER_FLAGS="$STD_LINKER_FLAGS" \
|
||||||
-DCTI_CONTINUABLE_WITH_NO_EXCEPTIONS=$WITH_NO_EXCEPTIONS -DCTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE=$WITH_AWAIT -DCTI_CONTINUABLE_WITH_LIGHT_TESTS=$WITH_LIGHT_TESTS \
|
-DCTI_CONTINUABLE_WITH_NO_EXCEPTIONS=$WITH_NO_EXCEPTIONS -DCTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE=$WITH_AWAIT -DCTI_CONTINUABLE_WITH_LIGHT_TESTS=$WITH_LIGHT_TESTS \
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug ..
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=$BUILD_CONFIG ..
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $CXX == *"clang"* ]]; then
|
if [[ $CXX == *"clang"* ]]; then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user