Promisify all and any callbacks

This commit is contained in:
Denis Blank 2017-10-03 20:08:48 +02:00
parent 40588e4e6e
commit 2dd1b9f361
2 changed files with 50 additions and 29 deletions

View File

@ -38,8 +38,10 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <continuable/continuable-promise-base.hpp>
#include <continuable/detail/api.hpp> #include <continuable/detail/api.hpp>
#include <continuable/detail/base.hpp> #include <continuable/detail/base.hpp>
#include <continuable/detail/hints.hpp>
#include <continuable/detail/traits.hpp> #include <continuable/detail/traits.hpp>
#include <continuable/detail/types.hpp> #include <continuable/detail/types.hpp>
@ -130,6 +132,26 @@ class all_result_submitter : public std::enable_shared_from_this<
std::once_flag flag_; std::once_flag flag_;
std::tuple<Args...> result_; std::tuple<Args...> result_;
template <std::size_t From, std::size_t To>
struct partial_callback {
std::shared_ptr<all_result_submitter> me_;
template <typename... PartialArgs>
void operator()(PartialArgs&&... args) {
me_->resolve(traits::size_constant<From>{}, traits::size_constant<To>{},
std::forward<PartialArgs>(args)...);
}
template <typename... PartialArgs>
void set_value(PartialArgs&&... args) {
(*this)(std::forward<PartialArgs>(args)...);
}
void set_exception(types::error_type error) {
(*this)(types::dispatch_error_tag{}, std::move(error));
}
};
public: public:
explicit all_result_submitter(T callback) explicit all_result_submitter(T callback)
: callback_(std::move(callback)), left_(Submissions) { : callback_(std::move(callback)), left_(Submissions) {
@ -139,13 +161,7 @@ public:
template <std::size_t From, std::size_t To> template <std::size_t From, std::size_t To>
auto create_callback(traits::size_constant<From> /*from*/, auto create_callback(traits::size_constant<From> /*from*/,
traits::size_constant<To> /*to*/) { traits::size_constant<To> /*to*/) {
return partial_callback<From, To>{this->shared_from_this()};
return [me = this->shared_from_this()](auto&&... args) {
// Resolve the and composition with the given arguments at the
// stored position
me->resolve(traits::size_constant<From>{}, traits::size_constant<To>{},
std::forward<decltype(args)>(args)...);
};
} }
private: private:
@ -195,9 +211,12 @@ private:
}; };
/// Invokes the callback with the first arriving result /// Invokes the callback with the first arriving result
template <typename T> template <typename Signature, typename T>
class any_result_submitter class any_result_submitter;
: public std::enable_shared_from_this<any_result_submitter<T>>, template <typename... Args, typename T>
class any_result_submitter<hints::signature_hint_tag<Args...>, T>
: public std::enable_shared_from_this<
any_result_submitter<hints::signature_hint_tag<Args...>, T>>,
public util::non_movable { public util::non_movable {
T callback_; T callback_;
@ -209,16 +228,21 @@ public:
/// Creates a submitter which submits it's result to the callback /// Creates a submitter which submits it's result to the callback
auto create_callback() { auto create_callback() {
return [me = this->shared_from_this()](auto&&... args) { auto callback = [me = this->shared_from_this()](auto&&... args) {
me->invoke(std::forward<decltype(args)>(args)...); me->invoke(std::forward<decltype(args)>(args)...);
}; };
return promise_base<std::decay_t<decltype(callback)>,
hints::signature_hint_tag<Args...>>(
std::move(callback));
} }
private: private:
// Invokes the callback with the given arguments // Invokes the callback with the given arguments
template <typename... Args> template <typename... ActualArgs>
void invoke(Args&&... args) { void invoke(ActualArgs&&... args) {
std::call_once(flag_, std::move(callback_), std::forward<Args>(args)...); std::call_once(flag_, std::move(callback_),
std::forward<ActualArgs>(args)...);
} }
}; };
} // namespace detail } // namespace detail
@ -355,10 +379,10 @@ auto finalize_composition(
} }
/// Creates a submitter that continues `any` chains /// Creates a submitter that continues `any` chains
template <typename Callback> template <typename Signature, typename Callback>
auto make_any_result_submitter(Callback&& callback) { auto make_any_result_submitter(Signature&& /*signature*/, Callback&& callback) {
return std::make_shared< return std::make_shared<detail::any_result_submitter<
detail::any_result_submitter<std::decay_t<decltype(callback)>>>( std::decay_t<Signature>, std::decay_t<decltype(callback)>>>(
std::forward<decltype(callback)>(callback)); std::forward<decltype(callback)>(callback));
} }
@ -409,13 +433,15 @@ auto finalize_composition(
base::hint_of(traits::identity_of(args))...); base::hint_of(traits::identity_of(args))...);
}); });
using Signature = decltype(signature);
return base::attorney::create( return base::attorney::create(
[composition = std::move(composition)](auto&& callback) mutable { [composition = std::move(composition)](auto&& callback) mutable {
// Create the submitter which calls the given callback once at the first // Create the submitter which calls the given callback once at the first
// callback invocation. // callback invocation.
auto submitter = make_any_result_submitter( auto submitter = make_any_result_submitter(
std::forward<decltype(callback)>(callback)); Signature{}, std::forward<decltype(callback)>(callback));
traits::static_for_each_in(std::move(composition), traits::static_for_each_in(std::move(composition),
[&](auto&& entry) mutable { [&](auto&& entry) mutable {

View File

@ -89,11 +89,9 @@ 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&& callback) mutable { auto&& promise) mutable {
cti::detail::traits::unpack(std::move(values), [&](auto&&... passed) { cti::detail::traits::unpack(std::move(values), [&](auto&&... passed) {
// ... promise.set_value(std::forward<decltype(passed)>(passed)...);
std::forward<decltype(callback)>(callback)(
std::forward<decltype(passed)>(passed)...);
}); });
}; };
} }
@ -104,8 +102,8 @@ public:
template <typename T> template <typename T>
auto invoke(T&& type) { auto invoke(T&& type) {
return this->make(identity<>{}, identity<void>{}, return this->make(identity<>{}, identity<void>{},
[type = std::forward<T>(type)](auto&& callback) mutable { [type = std::forward<T>(type)](auto&& promise) mutable {
std::forward<decltype(callback)>(callback)(); promise.set_value();
}); });
} }
@ -120,10 +118,7 @@ public:
}; };
inline auto empty_caller() { inline auto empty_caller() {
return [](auto&& callback) { return [](auto&& promise) { promise.set_value(); };
// ...
std::forward<decltype(callback)>(callback)();
};
} }
inline auto empty_continuable() { inline auto empty_continuable() {