mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Started to implement combined path callables
This commit is contained in:
parent
7dcd18c964
commit
52cf1ab929
@ -65,6 +65,11 @@ public:
|
||||
void operator()(Args... args) {
|
||||
data_(std::move(args)...);
|
||||
}
|
||||
/// Resolves the continuation with the given exception
|
||||
void operator()(detail::types::dispatch_error_tag tag,
|
||||
detail::types::error_type exception) {
|
||||
data_(tag, std::move(exception));
|
||||
}
|
||||
|
||||
/// Resolves the continuation with the given values
|
||||
void set_value(Args... args) {
|
||||
|
||||
@ -259,6 +259,39 @@ void packed_dispatch(Executor&& executor, Invoker&& invoker, Args&&... args) {
|
||||
}
|
||||
|
||||
namespace callbacks {
|
||||
template <typename Base>
|
||||
struct error_handler_base {
|
||||
void operator()(types::dispatch_error_tag, types::error_type error) {
|
||||
// Just invoke the error handler, cancel the calling hierarchy after
|
||||
auto invoker = [](typename Base::CallbackT&& callback,
|
||||
types::error_type&& error) {
|
||||
std::move(callback)(std::move(error));
|
||||
};
|
||||
|
||||
// Invoke the error handler
|
||||
packed_dispatch(
|
||||
std::move(static_cast<Base*>(this)->executor_), std::move(invoker),
|
||||
std::move(static_cast<Base*>(this)->callback_), std::move(error));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base, typename = void>
|
||||
struct result_callback_error_base {
|
||||
/// The operator which is called when an error occurred
|
||||
void operator()(types::dispatch_error_tag tag, types::error_type error) {
|
||||
// Forward the error to the next callback
|
||||
std::move(static_cast<Base*>(this)->next_callback_)(tag, std::move(error));
|
||||
}
|
||||
};
|
||||
template <typename Base>
|
||||
struct result_callback_error_base<
|
||||
Base, std::enable_if_t<util::is_invokable<
|
||||
typename Base::Callback,
|
||||
std::tuple<types::dispatch_error_tag, types::error_type>>::value>>
|
||||
: error_handler_base<Base> {
|
||||
using error_handler_base<Base>::operator();
|
||||
};
|
||||
|
||||
template <typename Hint, typename Callback, typename Executor,
|
||||
typename NextCallback>
|
||||
struct result_callback;
|
||||
@ -266,11 +299,23 @@ struct result_callback;
|
||||
template <typename... Args, typename Callback, typename Executor,
|
||||
typename NextCallback>
|
||||
struct result_callback<hints::signature_hint_tag<Args...>, Callback, Executor,
|
||||
NextCallback> {
|
||||
NextCallback>
|
||||
: result_callback_error_base<
|
||||
result_callback<hints::signature_hint_tag<Args...>, Callback,
|
||||
Executor, NextCallback>> {
|
||||
|
||||
using CallbackT = Callback;
|
||||
|
||||
Callback callback_;
|
||||
Executor executor_;
|
||||
NextCallback next_callback_;
|
||||
|
||||
explicit result_callback(Callback callback, Executor executor,
|
||||
NextCallback next_callback)
|
||||
: callback_(std::move(callback)), executor_(std::move(executor)),
|
||||
next_callback_(std::move(next_callback)) {
|
||||
}
|
||||
|
||||
/// The operator which is called when the result was provided
|
||||
void operator()(Args... args) {
|
||||
// In order to retrieve the correct decorator we must know what the
|
||||
@ -287,11 +332,7 @@ struct result_callback<hints::signature_hint_tag<Args...>, Callback, Executor,
|
||||
std::move(args)...);
|
||||
}
|
||||
|
||||
/// The operator which is called when an error occurred
|
||||
void operator()(types::dispatch_error_tag tag, types::error_type error) {
|
||||
// Forward the error to the next callback
|
||||
std::move(next_callback_)(tag, std::move(error));
|
||||
}
|
||||
using result_callback_error_base<result_callback>::operator();
|
||||
|
||||
/// Resolves the continuation with the given values
|
||||
void set_value(Args... args) {
|
||||
@ -311,29 +352,29 @@ struct error_callback;
|
||||
template <typename... Args, typename Callback, typename Executor,
|
||||
typename NextCallback>
|
||||
struct error_callback<hints::signature_hint_tag<Args...>, Callback, Executor,
|
||||
NextCallback> {
|
||||
NextCallback>
|
||||
: error_handler_base<error_callback<hints::signature_hint_tag<Args...>,
|
||||
Callback, Executor, NextCallback>> {
|
||||
|
||||
using CallbackT = Callback;
|
||||
|
||||
Callback callback_;
|
||||
Executor executor_;
|
||||
NextCallback next_callback_;
|
||||
|
||||
explicit error_callback(Callback callback, Executor executor,
|
||||
NextCallback next_callback)
|
||||
: callback_(std::move(callback)), executor_(std::move(executor)),
|
||||
next_callback_(std::move(next_callback)) {
|
||||
}
|
||||
|
||||
/// The operator which is called when the result was provided
|
||||
void operator()(Args... args) {
|
||||
// Forward the arguments to the next callback
|
||||
std::move(next_callback_)(std::move(args)...);
|
||||
}
|
||||
|
||||
/// The operator which is called when an error occurred
|
||||
void operator()(types::dispatch_error_tag /*tag*/, types::error_type error) {
|
||||
|
||||
// Just invoke the error handler, cancel the calling hierarchy after
|
||||
auto invoker = [](Callback&& callback, types::error_type&& error) {
|
||||
std::move(callback)(std::move(error));
|
||||
};
|
||||
|
||||
// Invoke the error handler
|
||||
packed_dispatch(std::move(executor_), std::move(invoker),
|
||||
std::move(callback_), std::move(error));
|
||||
}
|
||||
using error_handler_base<error_callback>::operator();
|
||||
|
||||
/// Resolves the continuation with the given values
|
||||
void set_value(Args... args) {
|
||||
|
||||
@ -34,7 +34,9 @@
|
||||
#include <future>
|
||||
|
||||
#include <continuable/detail/api.hpp>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/hints.hpp>
|
||||
#include <continuable/detail/types.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
@ -90,6 +92,14 @@ public:
|
||||
void operator()(Args... args) {
|
||||
this->resolve(promise_, std::move(args)...);
|
||||
}
|
||||
#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \
|
||||
!defined(CONTINUABLE_WITH_NO_EXCEPTIONS)
|
||||
/// Resolves the promise through the exception
|
||||
void operator()(types::dispatch_error_tag, types::error_type error) {
|
||||
promise_.set_exception(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Returns the future from the promise
|
||||
auto get_future() {
|
||||
return promise_.get_future();
|
||||
|
||||
@ -73,10 +73,10 @@ struct is_invokable_impl<
|
||||
/// arguments inside lambda closures.
|
||||
///
|
||||
/// ```cpp
|
||||
/// traits::is_invokable_t<object, std::tuple<Args...>>
|
||||
/// traits::is_invokable<object, std::tuple<Args...>>
|
||||
/// ```
|
||||
template <typename T, typename Args>
|
||||
using is_invokable_t = typename detail::is_invokable_impl<T, Args>::type;
|
||||
using is_invokable = typename detail::is_invokable_impl<T, Args>::type;
|
||||
|
||||
namespace detail {
|
||||
/// Forwards every element in the tuple except the last one
|
||||
@ -124,7 +124,7 @@ auto partial_invoke_impl(std::false_type, T&& callable,
|
||||
auto next = forward_except_last(std::move(args));
|
||||
|
||||
// Test whether we are able to call the function with the given tuple
|
||||
is_invokable_t<decltype(callable), decltype(next)> is_invokable;
|
||||
is_invokable<decltype(callable), decltype(next)> is_invokable;
|
||||
|
||||
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
|
||||
std::move(next));
|
||||
@ -157,7 +157,7 @@ auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
|
||||
template <typename T, typename... Args>
|
||||
auto partial_invoke(T&& callable, Args&&... args) {
|
||||
// Test whether we are able to call the function with the given arguments.
|
||||
is_invokable_t<decltype(callable), std::tuple<Args...>> is_invokable;
|
||||
is_invokable<decltype(callable), std::tuple<Args...>> is_invokable;
|
||||
|
||||
// The implementation is done in a shortcut way so there are less
|
||||
// type instantiations needed to call the callable with its full signature.
|
||||
|
||||
@ -57,7 +57,18 @@ static cti::continuable<std::string> http_request3(std::string url) {
|
||||
};
|
||||
}
|
||||
|
||||
struct my_callable {
|
||||
void operator()(std::string) {
|
||||
// ...
|
||||
}
|
||||
void operator()(cti::dispatch_error_tag, cti::error_type) {
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
http_request("github.com").then(my_callable{});
|
||||
|
||||
http_request("github.com")
|
||||
.then([](std::string) {
|
||||
// ...
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user