Skip to content

Commit b429c27

Browse files
authored
Merge pull request #37 from beman-project/add-overview
Add overview
2 parents d6a6c17 + 8837528 commit b429c27

File tree

6 files changed

+588
-5
lines changed

6 files changed

+588
-5
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ set(TARGET_LIBRARY beman_${TARGET_NAME})
1212
set(TARGET_ALIAS beman::${TARGET_NAME})
1313
set(TARGETS_EXPORT_NAME ${CMAKE_PROJECT_NAME}Targets)
1414

15-
set(CMAKE_CXX_STANDARD 23)
15+
set(CMAKE_CXX_STANDARD 26)
1616

1717
include(CTest)
1818
if(BUILD_TESTING)

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
<!--
2+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
-->
14
# beman.execution26: Building Block For Asynchronous Programs
25

36
`beman.execution26` provides the basic vocabulary for asynchronous

docs/overview.md

+462
Large diffs are not rendered by default.

examples/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(BEMAN_EXECUTION26_LIBRARY beman_${TARGET_NAME})
77

88
set(EXAMPLES
99
stop_token
10+
stopping
1011
)
1112

1213
foreach(EXAMPLE ${EXAMPLES})

examples/stopping.cpp

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// examples/stopping.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
// The example shows a bit of how cancellation works:
5+
// It creates work with a sender injecting a stop token
6+
// which gets started in a thread. To stop this thread
7+
// the corresponding stop source is requested to stop.
8+
9+
#include <beman/execution26/execution.hpp>
10+
#include <beman/execution26/stop_token.hpp>
11+
#include <chrono>
12+
#include <iostream>
13+
#include <thread>
14+
#include <cassert>
15+
16+
using namespace std::chrono;
17+
namespace ex = beman::execution26;
18+
19+
// ----------------------------------------------------------------------------
20+
21+
struct env
22+
{
23+
ex::inplace_stop_token token;
24+
25+
env(ex::inplace_stop_token token): token(token) {}
26+
27+
auto query(ex::get_stop_token_t const&) const noexcept {
28+
return this->token;
29+
}
30+
};
31+
32+
template <typename Sender>
33+
struct inject_cancel_sender
34+
{
35+
using sender_concept = ex::sender_t;
36+
37+
38+
template <typename Receiver>
39+
struct receiver
40+
{
41+
using receiver_concept = ex::receiver_t;
42+
43+
std::remove_cvref_t<Receiver> inner_receiver;
44+
ex::inplace_stop_token token{};
45+
46+
auto get_env() const noexcept -> env {
47+
return {this->token};
48+
}
49+
50+
template <typename... T>
51+
auto set_value(T&&... t) noexcept -> void {
52+
ex::set_value(std::move(inner_receiver), std::forward<T>(t)...);
53+
}
54+
template <typename E>
55+
auto set_error(E&& e) noexcept -> void {
56+
ex::set_error(std::move(inner_receiver), std::forward<E>(e));
57+
}
58+
auto set_stopped() noexcept -> void {
59+
ex::set_stopped(std::move(inner_receiver));
60+
}
61+
};
62+
63+
template <typename E>
64+
auto get_completion_signatures(E const&) {
65+
return ex::get_completion_signatures(this->sender, env{ex::inplace_stop_token{}});
66+
}
67+
68+
ex::inplace_stop_token token{};
69+
Sender sender;
70+
71+
template <typename Receiver>
72+
auto connect(Receiver&& recv) && {
73+
return ex::connect(std::move(sender), receiver<Receiver>{std::forward<Receiver>(recv), this->token});
74+
}
75+
};
76+
77+
template <typename S>
78+
inject_cancel_sender(ex::inplace_stop_token, S&&) -> inject_cancel_sender<std::decay_t<S>>;
79+
80+
struct receiver
81+
{
82+
using receiver_concept = ex::receiver_t;
83+
auto set_value(auto&&...) noexcept -> void {}
84+
auto set_error(auto&&) noexcept -> void {}
85+
auto set_stopped() noexcept -> void {}
86+
};
87+
88+
int main()
89+
{
90+
ex::inplace_stop_source source;
91+
92+
std::thread t([token=source.get_token()]{
93+
ex::sync_wait(
94+
inject_cancel_sender{token,
95+
ex::read_env(ex::get_stop_token)
96+
| ex::then([](ex::inplace_stop_token tok){
97+
while (not tok.stop_requested())
98+
{
99+
std::cout << "sleeping\n";
100+
std::this_thread::sleep_for(1s);
101+
}
102+
})
103+
});
104+
}
105+
);
106+
107+
std::cin.get();
108+
std::cout << "requesting stop\n";
109+
source.request_stop();
110+
111+
t.join();
112+
}
113+

src/beman/execution26/tests/exec-get-delegation-scheduler.pass.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ namespace
2828
}
2929

3030
template <typename Tag>
31-
auto query(test_std::get_completion_scheduler_t<Tag> const&) const noexcept
32-
{
33-
return scheduler{this->value};
34-
}
31+
auto query(test_std::get_completion_scheduler_t<Tag> const&) const noexcept;
3532
};
3633

3734
struct scheduler
@@ -53,6 +50,13 @@ namespace
5350
auto schedule() noexcept -> sender { return {this->value}; }
5451
auto operator== (scheduler const&) const -> bool = default;
5552
};
53+
54+
template <bool Noexcept, typename Scheduler>
55+
template <typename Tag>
56+
auto env<Noexcept, Scheduler>::query(test_std::get_completion_scheduler_t<Tag> const&) const noexcept
57+
{
58+
return scheduler{this->value};
59+
}
5660

5761
template <bool Expect, typename Scheduler = void>
5862
auto test_get_delegation_scheduler(auto&& env) -> void

0 commit comments

Comments
 (0)