// Copyright (c) OpenMMLab. All rights reserved. // Modified from // https://github.com/brycelelbach/wg21_p2300_std_execution/blob/main/include/execution.hpp #ifndef MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_THEN_H_ #define MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_THEN_H_ #include "closure.h" #include "concepts.h" #include "utility.h" namespace mmdeploy { namespace __then { template struct _Receiver { struct type; }; template using receiver_t = typename _Receiver::type; template struct _Receiver::type { Receiver receiver_; Func func_; template friend void tag_invoke(set_value_t, type&& self, Args&&... args) noexcept { if constexpr (std::is_void_v>) { std::invoke(std::move(self.func_), (Args &&) args...); SetValue(std::move(self.receiver_)); } else { SetValue(std::move(self.receiver_), std::invoke(std::move(self.func_), (Args &&) args...)); } } }; template struct _Sender { struct type; }; template using sender_t = typename _Sender, remove_cvref_t>::type; template struct _Sender::type { using _ret_type = decltype( std::apply(std::declval(), std::declval>())); using value_types = std::conditional_t, std::tuple<>, std::tuple<_ret_type>>; Sender sender_; Func func_; template = 0> friend auto tag_invoke(connect_t, Self&& self, Receiver&& receiver) { return Connect(((Self &&) self).sender_, receiver_t{(Receiver &&) receiver, std::move(self.func_)}); } template friend auto tag_invoke(get_completion_scheduler_t, const type& self) noexcept -> tag_invoke_result_t { return GetCompletionScheduler(self.sender_); } }; struct then_t { template && _tag_invocable_with_completion_scheduler, int> = 0> auto operator()(Sender&& sender, Func func) const { auto scheduler = GetCompletionScheduler(sender); return tag_invoke(then_t{}, std::move(scheduler), (Sender &&) sender, std::move(func)); } template && !_tag_invocable_with_completion_scheduler && tag_invocable, int> = 0> auto operator()(Sender&& sender, Func func) const { auto scheduler = GetCompletionScheduler(sender); return tag_invoke(then_t{}, std::move(scheduler), (Sender &&) sender, std::move(func)); } template && !_tag_invocable_with_completion_scheduler && !tag_invocable, int> = 0> sender_t operator()(Sender&& sender, Func func) const { return {(Sender &&) sender, std::move(func)}; } template _BinderBack operator()(Func func) const { return {{}, {}, {std::move(func)}}; } }; } // namespace __then using __then::then_t; inline constexpr then_t Then; } // namespace mmdeploy #endif // MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_THEN_H_