Skip to content

Commit b4b585f

Browse files
committed
added sync_wait
1 parent 66a35f7 commit b4b585f

File tree

6 files changed

+307
-18
lines changed

6 files changed

+307
-18
lines changed

Makefile

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
# Makefile
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

4-
SANITIZERS = none msan asan usan tsan
4+
SANITIZERS = none debug msan asan usan tsan
55
.PHONY: default update check ce todo distclean clean build test all $(SANITIZERS)
66

77
CXX_FLAGS = -g
88
SANITIZER = none
99
BUILDROOT = build
10-
BUILD = $(BUILDROOT)/none
10+
BUILD = $(BUILDROOT)/$(SANITIZER)
1111

1212
ifeq ($(SANITIZER),none)
1313
CXX_FLAGS = -O3 -pedantic -Wall -Wextra -Werror
1414
endif
15+
ifeq ($(SANITIZER),debug)
16+
CXX_FLAGS = -g
17+
endif
1518
ifeq ($(SANITIZER),usan)
1619
SAN_FLAGS = -fsanitize=memory
1720
BUILD = $(BUILDROOT)/msan
@@ -39,6 +42,7 @@ default: test
3942
all: $(SANITIZERS)
4043

4144
none: test
45+
4246
$(SANITIZERS):
4347
$(MAKE) SANITIZER=$@
4448

docs/questions.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,17 @@ likely observable.
2929
have completion_signatures defined - should the constaint be sender_in
3030
instead of sender? oh, actually, only the result of transform_sender needs
3131
to be a sender_in!
32-
- [exec.sync.wait] p4.2: what is "e"? probably apply_sender(...)
32+
- [exec.sync.wait] p4.2: what is "e"? probably apply_sender(...)
33+
- [exec.sync.wait] p9 seems to be wrong: the sender needs to be scheduled
34+
somehow. Consider using sync_wait(execution::just()). The operation
35+
immediately completes, calling into sync_wait_receiver::set_value which
36+
in turn calls loop.finish(). When the loop then is run() it immediately
37+
std::terminate()s because the run_loop's state is finished not starting.
38+
I can see two potential fixes:
39+
1. connect(on(sender), sync-wait-receiver<Sndr>{&state})
40+
2. have run_loop::run() only terminate when the state is running; if
41+
the state is already finishing, leave it at that
42+
- [exec.sync_wait] are sync_wait(just_error(17)) and sync_wait(just_stopped())
43+
supposed to work? I don't see a reason why a value completion is necessarily
44+
required. As is, they are not because type_idenity_t ends up being used without
45+
argument.

include/beman/execution26/detail/get_delegation_scheduler.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace beman::execution26
2020
{ ::std::as_const(env).query(g) } noexcept
2121
-> ::beman::execution26::scheduler;
2222
}
23-
auto operator()(Env&& env) const
23+
auto operator()(Env&& env) const noexcept
2424
{
2525
return ::std::as_const(env).query(*this);
2626
}

include/beman/execution26/detail/run_loop.hpp

+6-7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <mutex>
2121
#include <type_traits>
2222
#include <utility>
23+
#include <iostream> //-dk:TODO remove
2324

2425
// ----------------------------------------------------------------------------
2526

@@ -54,7 +55,7 @@ namespace beman::execution26
5455
using operation_state_concept = ::beman::execution26::operation_state_t;
5556

5657
run_loop* loop;
57-
Receiver receiver;
58+
Receiver receiver;
5859

5960
template <typename R>
6061
opstate(run_loop* loop, R&& receiver)
@@ -161,13 +162,11 @@ namespace beman::execution26
161162

162163
auto run() -> void
163164
{
165+
if (::std::lock_guard guard(this->mutex);
166+
this->current_state != state::finishing
167+
&& state::running == ::std::exchange(this->current_state, state::running))
164168
{
165-
::std::lock_guard guard(this->mutex);
166-
auto current{::std::exchange(this->current_state, state::running)};
167-
if (state::starting != current)
168-
{
169-
::std::terminate();
170-
}
169+
::std::terminate();
171170
}
172171

173172
while (auto* op{this->pop_front()})

include/beman/execution26/detail/sync_wait.hpp

+47-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SYNC_WAIT
55
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SYNC_WAIT
66

7+
#include <beman/execution26/detail/as_except_ptr.hpp>
78
#include <beman/execution26/detail/sender_in.hpp>
89
#include <beman/execution26/detail/get_domain_early.hpp>
910
#include <beman/execution26/detail/get_scheduler.hpp>
@@ -13,9 +14,13 @@
1314
#include <beman/execution26/detail/start.hpp>
1415
#include <beman/execution26/detail/run_loop.hpp>
1516
#include <beman/execution26/detail/receiver.hpp>
17+
#include <beman/execution26/detail/sender_in.hpp>
18+
#include <beman/execution26/detail/value_types_of_t.hpp>
19+
#include <beman/execution26/detail/decayed_tuple.hpp>
1620
#include <exception>
1721
#include <optional>
1822
#include <utility>
23+
#include <type_traits>
1924

2025
// ----------------------------------------------------------------------------
2126

@@ -28,7 +33,7 @@ namespace beman::execution26::detail
2833
{
2934
struct sync_wait_env
3035
{
31-
::beman::execution26::run_loop* loop;
36+
::beman::execution26::run_loop* loop{};
3237

3338
auto query(::beman::execution26::get_scheduler_t) const noexcept
3439
{
@@ -40,12 +45,24 @@ namespace beman::execution26::detail
4045
}
4146
};
4247

48+
template <::beman::execution26::sender_in Sender>
49+
using sync_wait_result_type
50+
= ::std::optional<
51+
::beman::execution26::value_types_of_t<
52+
Sender,
53+
::beman::execution26::detail::sync_wait_env,
54+
::beman::execution26::detail::decayed_tuple,
55+
::std::type_identity_t
56+
>
57+
>;
58+
4359
template <typename Sender>
4460
struct sync_wait_state
4561
{
4662
be::run_loop loop{};
4763
::std::exception_ptr error{};
48-
::std::optional<int> result{};
64+
65+
::beman::execution26::detail::sync_wait_result_type<Sender> result{};
4966
};
5067

5168
template <typename Sender>
@@ -55,18 +72,30 @@ namespace beman::execution26::detail
5572

5673
bed::sync_wait_state<Sender>* state{};
5774

58-
auto set_error(auto&&) && noexcept -> void
75+
template <typename Error>
76+
auto set_error(Error&& error) && noexcept -> void
5977
{
60-
/*-dk:TODO set state->error */
78+
this->state->error
79+
= ::beman::execution26::detail::as_except_ptr(
80+
::std::forward<Error>(error)
81+
);
6182
this->state->loop.finish();
6283
}
6384
auto set_stopped() && noexcept -> void
6485
{
6586
this->state->loop.finish();
6687
}
67-
auto set_value(auto&&...) && noexcept -> void
88+
template <typename... Args>
89+
auto set_value(Args&&... args) && noexcept -> void
6890
{
69-
/*-dk:TODO set state->result */
91+
try
92+
{
93+
this->state->result.emplace(::std::forward<Args>(args)...);
94+
}
95+
catch(...)
96+
{
97+
this->state->error = ::std::current_exception();
98+
}
7099
this->state->loop.finish();
71100
}
72101

@@ -92,6 +121,18 @@ namespace beman::execution26::detail
92121

93122
template <::beman::execution26::sender_in<
94123
::beman::execution26::detail::sync_wait_env> Sender>
124+
requires requires(Sender&& sender, sync_wait_t const& self){
125+
typename ::beman::execution26::detail::sync_wait_result_type<Sender>;
126+
{
127+
::beman::execution26::apply_sender(
128+
::beman::execution26::detail::get_domain_early(sender),
129+
self,
130+
::std::forward<Sender>(sender)
131+
)
132+
} -> ::std::same_as<
133+
::beman::execution26::detail::sync_wait_result_type<Sender>
134+
>;
135+
}
95136
auto operator()(Sender&& sender) const
96137
{
97138
auto domain{::beman::execution26::detail::get_domain_early(sender)};

0 commit comments

Comments
 (0)