Skip to content

Commit e1f37e9

Browse files
authored
Merge pull request #63 from beman-project/add-simple-sender-creation-example
Add simple sender creation example
2 parents 5b830fe + 88f9ade commit e1f37e9

File tree

7 files changed

+108
-10
lines changed

7 files changed

+108
-10
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

44
SANITIZERS = release debug msan asan usan tsan
5-
.PHONY: default run update check ce todo distclean clean build test all $(SANITIZERS)
5+
.PHONY: default run update check ce todo distclean clean build test all format $(SANITIZERS)
66

77
COMPILER=system
88
CXX_BASE=$(CXX:$(dir $(CXX))%=%)
@@ -79,6 +79,9 @@ check:
7979
< $$h sed -n "/^ *# *include <Beman\//s@.*[</]Beman/\(.*\).hpp>.*@$$from \1@p"; \
8080
done | tsort > /dev/null
8181

82+
format:
83+
clang-format -i `git diff --name-only main | egrep '\.[ch]pp'`
84+
8285
todo:
8386
bin/mk-todo.py
8487

examples/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
# cmake-format: on
55

6-
list(APPEND EXAMPLES when_all-cancel stop_token stopping allocator)
6+
list(APPEND EXAMPLES sender-demo when_all-cancel stop_token stopping allocator)
77

88
foreach(EXAMPLE ${EXAMPLES})
99
set(EXAMPLE_TARGET ${TARGET_PREFIX}.examples.${EXAMPLE})

examples/just_stopped.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <beman/execution26/execution.hpp>
2+
namespace ex = beman::execution26;
3+
4+
struct receiver {
5+
using receiver_concept = ex::receiver_t;
6+
auto set_value(auto&&...) noexcept -> void {}
7+
auto set_error(auto&&) noexcept -> void {}
8+
auto set_stopped() noexcept -> void {}
9+
};
10+
11+
int main() {
12+
// ex::sync_wait(ex::just_stopped() | ex::then([]{}));
13+
auto then = ex::just_stopped() | ex::then([] {});
14+
static_assert(std::same_as<void, decltype(ex::get_completion_signatures(then, ex::empty_env()))>);
15+
16+
ex::connect(ex::just_stopped() | ex::then([] {}), receiver{});
17+
}

examples/sender-demo.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include <beman/execution26/execution.hpp>
2+
#include <type_traits>
3+
#include <string>
4+
#include <memory_resource>
5+
#include <utility>
6+
#include <iostream>
7+
8+
namespace ex = beman::execution26;
9+
10+
template <typename Receiver>
11+
struct just_op_state {
12+
using operation_state_concept = ex::operation_state_t;
13+
std::remove_cvref_t<Receiver> rec;
14+
std::pmr::string value;
15+
16+
template <typename R>
17+
just_op_state(R&& r, std::pmr::string&& value)
18+
: rec(std::forward<R>(r)), value(std::move(value), ex::get_allocator(ex::get_env(rec))) {}
19+
20+
void start() & noexcept { ex::set_value(std::move(rec), std::move(value)); }
21+
};
22+
23+
struct test_receiver {
24+
using receiver_concept = ex::receiver_t;
25+
auto set_value(auto&&...) && noexcept -> void { std::cout << "set_value\n"; }
26+
auto set_error(auto&&) && noexcept -> void { std::cout << "set_error\n"; }
27+
auto set_stopped() && noexcept -> void { std::cout << "set_stopped\n"; }
28+
};
29+
30+
static_assert(ex::receiver<test_receiver>);
31+
static_assert(ex::operation_state<just_op_state<test_receiver>>);
32+
33+
template <typename T>
34+
struct just_sender {
35+
using sender_concept = ex::sender_t;
36+
using completion_signatures = ex::completion_signatures<ex::set_value_t(T)>;
37+
38+
T value;
39+
template <ex::receiver Receiver>
40+
auto connect(Receiver&& r) && -> just_op_state<Receiver> {
41+
return {std::forward<Receiver>(r), std::move(value)};
42+
}
43+
};
44+
45+
static_assert(ex::sender<just_sender<std::pmr::string>>);
46+
static_assert(ex::sender_in<just_sender<std::pmr::string>>);
47+
48+
int main() {
49+
auto j = just_sender{std::pmr::string("value")};
50+
auto t = std::move(j) | ex::then([](std::pmr::string v) { return v + " then"; });
51+
auto w = ex::when_all(std::move(t));
52+
auto e = ex::detail::write_env(std::move(w),
53+
ex::detail::make_env(ex::get_allocator, std::pmr::polymorphic_allocator<>()));
54+
55+
std::cout << "before start\n";
56+
auto r = ex::sync_wait(std::move(e));
57+
if (r) {
58+
auto [v] = *r;
59+
std::cout << "produced='" << v << "'\n";
60+
} else
61+
std::cout << "operation was cancelled\n";
62+
std::cout << "after start\n";
63+
}

include/beman/execution26/detail/get_allocator.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ struct get_allocator_t {
1919
auto operator()(Object&&) const =
2020
BEMAN_EXECUTION26_DELETE("the object requires a const query(get_allocator_t) overload");
2121
template <typename Object>
22-
requires(not requires(const Object& object, const get_allocator_t& tag) { object.query(tag); })
22+
requires(
23+
not requires(const Object& object, const get_allocator_t& tag) { object.query(tag); } &&
24+
not requires(Object&& object, const get_allocator_t& tag) { ::std::as_const(object).query(tag); })
2325
auto
2426
operator()(Object&&) const = BEMAN_EXECUTION26_DELETE("the object requires a query(get_allocator_t) overload");
2527
template <typename Object>
@@ -28,6 +30,7 @@ struct get_allocator_t {
2830
})
2931
auto
3032
operator()(Object&&) const = BEMAN_EXECUTION26_DELETE("the query(get_allocator_t) overload needs to be noexcept");
33+
3134
template <typename Object>
3235
requires(not requires(const Object& object, const get_allocator_t& tag) {
3336
{ object.query(tag) } noexcept -> ::beman::execution26::detail::simple_allocator<>;
@@ -36,7 +39,10 @@ struct get_allocator_t {
3639
operator()(Object&&) const = BEMAN_EXECUTION26_DELETE("the query(get_allocator_t) overload needs to be noexcept");
3740

3841
template <typename Object>
39-
auto operator()(Object&& object) const {
42+
requires(requires(const Object& object, const get_allocator_t& tag) {
43+
{ object.query(tag) } noexcept -> ::beman::execution26::detail::simple_allocator<>;
44+
})
45+
auto operator()(Object&& object) const noexcept {
4046
return ::std::as_const(object).query(*this);
4147
}
4248

include/beman/execution26/detail/simple_allocator.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
// ----------------------------------------------------------------------------
1111

1212
namespace beman::execution26::detail {
13-
template <typename Alloc = bool>
14-
concept simple_allocator = requires(Alloc alloc, ::std::size_t n) {
15-
{ *alloc.allocate(n) } -> ::std::same_as<typename Alloc::value_type&>;
16-
alloc.deallocate(alloc.allocate(n), n);
17-
} && ::std::copy_constructible<Alloc> && ::std::equality_comparable<Alloc>;
13+
template <typename Alloc>
14+
concept simple_allocator =
15+
requires(::std::remove_cvref_t<Alloc> alloc, ::std::size_t n) {
16+
{ *alloc.allocate(n) } -> ::std::same_as<typename ::std::remove_cvref_t<Alloc>::value_type&>;
17+
alloc.deallocate(alloc.allocate(n), n);
18+
} && ::std::copy_constructible<::std::remove_cvref_t<Alloc>> &&
19+
::std::equality_comparable<::std::remove_cvref_t<Alloc>>;
1820
} // namespace beman::execution26::detail
1921

2022
// ----------------------------------------------------------------------------

include/beman/execution26/detail/when_all.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,20 @@ template <typename Data, typename Env, typename... Sender>
231231
struct completion_signatures_for_impl<
232232
::beman::execution26::detail::basic_sender<::beman::execution26::detail::when_all_t, Data, Sender...>,
233233
Env> {
234+
template <typename... E>
235+
struct error_comps_t {
236+
using type = ::beman::execution26::completion_signatures<::beman::execution26::set_error_t(E)...>;
237+
};
238+
template <typename... E>
239+
using error_comps = typename error_comps_t<E...>::type;
240+
234241
using value_types =
235242
typename ::beman::execution26::detail::when_all_value_types<::beman::execution26::detail::meta::combine<
236243
::beman::execution26::
237244
value_types_of_t<Sender, Env, ::beman::execution26::detail::type_list, ::std::type_identity_t>...>>::
238245
type;
239246
using error_types = ::beman::execution26::detail::meta::unique<::beman::execution26::detail::meta::combine<
240-
::beman::execution26::error_types_of_t<Sender, Env, ::beman::execution26::completion_signatures>...>>;
247+
::beman::execution26::error_types_of_t<Sender, Env, error_comps>...>>;
241248
using type = ::beman::execution26::detail::meta::combine<value_types, error_types>;
242249
};
243250
} // namespace beman::execution26::detail

0 commit comments

Comments
 (0)