Skip to content

Commit b085c44

Browse files
authored
Fix bugs in as_awaitable, let_error and sync_wait (#253)
* Fix bugs in `as_awaitable` and `let_error` * Fix a use-after-free/data-race in `run_loop`/`sync_wait`
1 parent 8c46474 commit b085c44

4 files changed

Lines changed: 14 additions & 12 deletions

File tree

include/beman/execution/detail/as_awaitable.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace beman::execution {
4242
*/
4343
struct as_awaitable_t {
4444
template <typename Expr, typename Promise>
45-
auto operator()(Expr&& expr, Promise& promise) const {
45+
auto operator()(Expr&& expr, Promise& promise) const -> decltype(auto) {
4646
if constexpr (requires { ::std::forward<Expr>(expr).as_awaitable(promise); }) {
4747
static_assert(
4848
::beman::execution::detail::is_awaitable<decltype(::std::forward<Expr>(expr).as_awaitable(promise)),

include/beman/execution/detail/let.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import std;
1010
#else
1111
#include <concepts>
1212
#include <exception>
13+
#include <functional>
1314
#include <tuple>
1415
#include <type_traits>
1516
#include <utility>
@@ -271,12 +272,9 @@ struct let_t {
271272
{}};
272273
}};
273274
template <typename Receiver, typename... Args>
274-
static auto
275-
let_bind(auto& state, Receiver& receiver, Args&&... args) noexcept(noexcept(::beman::execution::connect(
276-
::std::apply(::std::move(state.fun),
277-
::std::move(state.args.template emplace<::beman::execution::detail::decayed_tuple<Args...>>(
278-
::std::forward<Args>(args)...))),
279-
let_receiver<Receiver, decltype(state.env)>{receiver, state.env}))) {
275+
static auto let_bind(auto& state, Receiver& receiver, Args&&... args) noexcept(
276+
noexcept(::beman::execution::connect(::std::invoke(::std::move(state.fun), ::std::forward<Args>(args)...),
277+
let_receiver<Receiver, decltype(state.env)>{receiver, state.env}))) {
280278
using args_t = ::beman::execution::detail::decayed_tuple<Args...>;
281279
auto mkop{[&] {
282280
return ::beman::execution::connect(

include/beman/execution/detail/run_loop.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,8 @@ class run_loop {
175175
}
176176
}
177177
auto finish() -> void {
178-
{
179-
::std::lock_guard guard(this->mutex);
180-
this->current_state = state::finishing;
181-
}
178+
::std::lock_guard guard(this->mutex);
179+
this->current_state = state::finishing;
182180
this->condition.notify_one();
183181
}
184182
};

tests/beman/execution/exec-spawn.test.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import beman.execution;
1111
import beman.execution.detail;
1212
#else
13+
#include <beman/execution/detail/just.hpp>
14+
#include <beman/execution/detail/let.hpp>
1315
#include <beman/execution/detail/spawn.hpp>
1416
#include <beman/execution/detail/sender.hpp>
1517
#include <beman/execution/detail/receiver.hpp>
@@ -188,11 +190,15 @@ auto test_spawn() {
188190
ASSERT(associated == false);
189191
ASSERT(disassociated == false);
190192
}
193+
static_assert(requires {
194+
test_std::spawn(test_std::just_error(0) | test_std::let_error([](int) noexcept { return test_std::just(); }),
195+
std::declval<token<true>>());
196+
});
191197
}
192198

193199
} // namespace
194200

195-
TEST(exec_spawn_future) {
201+
TEST(exec_spawn) {
196202
static_assert(std::same_as<decltype(test_std::spawn), const test_std::spawn_t>);
197203
test_overload<true>(sender<true>{}, token<true>{}, env{});
198204
test_overload<false>(sender<false>{}, token<true>{}, env{});

0 commit comments

Comments
 (0)