Iros
 
Loading...
Searching...
No Matches
sync_wait.h
Go to the documentation of this file.
1#pragma once
2
11#include "di/function/curry.h"
13#include "di/meta/core.h"
14#include "di/meta/util.h"
15
16namespace di::execution {
17namespace sync_wait_ns {
18 template<concepts::ExecutionContext Context>
20
21 template<typename Context>
22 struct EnvT {
23 struct Type {
24 public:
26
27 private:
28 constexpr friend auto tag_invoke(types::Tag<get_scheduler>, Type const& self) { return self.scheduler; }
29 constexpr friend auto tag_invoke(types::Tag<get_delegatee_scheduler>, Type const& self) {
30 return self.scheduler;
31 }
32 };
33 };
34
35 template<concepts::ExecutionContext Context>
37
38 template<typename Result, typename Context>
39 struct ReceiverT {
40 struct Type {
41 public:
42 using is_receiver = void;
43
44 explicit Type(Result* result, Context* context) : m_result(result), m_context(context) {}
45
46 private:
47 template<typename... Values>
48 friend auto tag_invoke(SetValue, Type&& self, Values&&... values)
49 requires(requires { util::declval<Result&>().emplace(util::forward<Values>(values)...); })
50 {
51 self.m_result->emplace(util::forward<Values>(values)...);
52 self.m_context->finish();
53 }
54
55 friend void tag_invoke(SetError, Type&& self, Error error) {
56 // FIXME: handle other error types than the generic type-erased error.
57 *self.m_result = Unexpected(util::move(error));
58 self.m_context->finish();
59 }
60 friend void tag_invoke(SetStopped, Type&& self) {
61 *self.m_result = Unexpected(BasicError::OperationCanceled);
62 self.m_context->finish();
63 }
64
65 constexpr friend auto tag_invoke(types::Tag<get_env>, Type const& self) {
66 return Env<Context>(self.m_context->get_scheduler());
67 }
68
69 Result* m_result;
70 Context* m_context;
71 };
72 };
73
74 template<typename Result, concepts::ExecutionContext Context>
76
77 template<concepts::ExecutionContext Context, concepts::SenderIn<Env<Context>> Send>
79
80 template<concepts::ExecutionContext Context, concepts::SenderIn<Env<Context>> Send>
82
83 template<typename T>
84 struct Uninit {
86 };
87
88 struct OnFunction {
89 template<concepts::ExecutionContext Context, concepts::SenderIn<Env<Context>> Send>
90 auto operator()(Context& context, Send&& sender) const -> concepts::SameAs<ResultType<Context, Send>> auto {
91 if constexpr (requires {
93 util::forward<Send>(sender));
94 }) {
96 util::forward<Send>(sender));
97 } else if constexpr (requires { function::tag_invoke(*this, context, util::forward<Send>(sender)); }) {
98 return function::tag_invoke(*this, context, util::forward<Send>(sender));
99 } else if constexpr (concepts::SequenceSender<Send>) {
100 static_assert(concepts::AlwaysFalse<Send>,
101 "sync_wait() cannot be called on sequences. Use a sequence consumer like ignore_all() or "
102 "first_value() before sync_wait().");
103 } else {
104 auto value = Uninit<ResultType<Context, Send>> {};
105
106 auto operation = execution::connect(util::forward<Send>(sender),
108 util::addressof(value.value), util::addressof(context)));
109 execution::start(operation);
110
111 context.run();
112
113 return util::move(value.value);
114 }
115 }
116 };
117
119 template<concepts::ExecutionContext Context, concepts::SenderIn<Env<Context>> Send>
120 auto operator()(Context& context, Send&& sender) const
122 if constexpr (requires {
124 util::forward<Send>(sender));
125 }) {
127 util::forward<Send>(sender));
128 } else if constexpr (requires { function::tag_invoke(*this, context, util::forward<Send>(sender)); }) {
129 return function::tag_invoke(*this, context, util::forward<Send>(sender));
130 } else {
131 return OnFunction {}(context, execution::into_variant(util::forward<Send>(sender)));
132 }
133 }
134 };
135
137 template<concepts::SenderIn<Env<RunLoop<>>> Send>
138 auto operator()(Send&& sender) const -> concepts::SameAs<ResultType<RunLoop<>, Send>> auto {
139 if constexpr (requires {
141 util::forward<Send>(sender));
142 }) {
144 util::forward<Send>(sender));
145 } else if constexpr (requires { function::tag_invoke(*this, util::forward<Send>(sender)); }) {
146 return function::tag_invoke(*this, util::forward<Send>(sender));
147 } else {
148 auto run_loop = RunLoop<> {};
149 return OnFunction {}(run_loop, util::forward<Send>(sender));
150 }
151 }
152 };
153
155 template<concepts::SenderIn<Env<RunLoop<>>> Send>
156 auto operator()(Send&& sender) const -> concepts::SameAs<WithVariantResultType<RunLoop<>, Send>> auto {
157 if constexpr (requires {
159 util::forward<Send>(sender));
160 }) {
162 util::forward<Send>(sender));
163 } else if constexpr (requires { function::tag_invoke(*this, util::forward<Send>(sender)); }) {
164 return function::tag_invoke(*this, util::forward<Send>(sender));
165 } else {
166 return Function {}(execution::into_variant(util::forward<Send>(sender)));
167 }
168 }
169 };
170}
171
172constexpr inline auto sync_wait = sync_wait_ns::Function {};
174
176constexpr inline auto sync_wait_with_variant_on =
178}
179
180namespace di {
185}
Definition run_loop.h:19
Definition unexpected.h:14
This concept is used with static_assert() to cause the static assert to fail only when the template h...
Definition core.h:98
Definition core.h:114
Definition sequence_sender.h:102
vocab::Result< meta::ValueTypesOf< Send, Env, ResultTypeImpl::template Invoke, ResultTypeConcatImpl::template Invoke > > ResultType
Definition into_result.h:57
vocab::Result< into_variant_ns::IntoVariantType< Send, Env > > WithVariantResultType
Definition into_result.h:61
Definition sync_wait.h:17
meta::Type< EnvT< Context > > Env
Definition sync_wait.h:36
meta::ExecutionContextScheduler< Context > Scheduler
Definition sync_wait.h:19
into_result_ns::WithVariantResultType< Env< Context >, Send > WithVariantResultType
Definition sync_wait.h:81
meta::Type< ReceiverT< Result, Context > > Receiver
Definition sync_wait.h:75
into_result_ns::ResultType< Env< Context >, Send > ResultType
Definition sync_wait.h:78
Definition bulk.h:30
constexpr auto start
Definition start.h:20
constexpr auto into_variant
Definition into_variant.h:86
constexpr auto sync_wait_with_variant_on
Definition sync_wait.h:176
constexpr auto get_completion_scheduler
Definition get_completion_scheduler.h:19
constexpr auto get_env
Definition get_env.h:27
constexpr auto sync_wait_on
Definition sync_wait.h:175
constexpr auto connect
Definition connect.h:42
constexpr auto sync_wait
Definition sync_wait.h:172
constexpr auto sync_wait_with_variant
Definition sync_wait.h:173
constexpr tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
constexpr auto curry
Definition curry.h:140
T::Type Type
Definition core.h:26
constexpr auto c_
A value of type Constexpr<val>.
Definition constexpr.h:252
decltype(util::declval< Context & >().get_scheduler()) ExecutionContextScheduler
Definition execution_context_scheduler.h:7
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
auto declval() -> meta::AddRValueReference< T >
Definition declval.h:8
Expected< T, Error > Result
Definition result.h:8
StatusCode< Erased< long > > Error
Definition error.h:8
Definition zstring_parser.h:9
Defines the sequence sender concepts and related CPOs.
Definition set_error.h:6
Definition set_stopped.h:6
Definition set_value.h:6
constexpr friend auto tag_invoke(types::Tag< get_scheduler >, Type const &self)
Definition sync_wait.h:28
Scheduler< Context > scheduler
Definition sync_wait.h:25
constexpr friend auto tag_invoke(types::Tag< get_delegatee_scheduler >, Type const &self)
Definition sync_wait.h:29
Definition sync_wait.h:22
Definition sync_wait.h:136
auto operator()(Send &&sender) const -> concepts::SameAs< ResultType< RunLoop<>, Send > > auto
Definition sync_wait.h:138
auto operator()(Context &context, Send &&sender) const -> concepts::SameAs< ResultType< Context, Send > > auto
Definition sync_wait.h:90
friend void tag_invoke(SetError, Type &&self, Error error)
Definition sync_wait.h:55
void is_receiver
Definition sync_wait.h:42
friend void tag_invoke(SetStopped, Type &&self)
Definition sync_wait.h:60
Type(Result *result, Context *context)
Definition sync_wait.h:44
constexpr friend auto tag_invoke(types::Tag< get_env >, Type const &self)
Definition sync_wait.h:65
friend auto tag_invoke(SetValue, Type &&self, Values &&... values)
Definition sync_wait.h:48
Definition sync_wait.h:84
T value
Definition sync_wait.h:85
auto operator()(Send &&sender) const -> concepts::SameAs< WithVariantResultType< RunLoop<>, Send > > auto
Definition sync_wait.h:156
auto operator()(Context &context, Send &&sender) const -> concepts::SameAs< WithVariantResultType< Context, Send > > auto
Definition sync_wait.h:120