Skip to content

Commit bfcfa6d

Browse files
committed
working version of finite_inplace_stop_source
1 parent 086af5b commit bfcfa6d

28 files changed

+594
-131
lines changed

CMakePresets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"patch": 0
77
},
88
"include": [
9-
"cmake/CMake${hostSystemName}Presets.json"
9+
"cmake/CMakeDarwinPresets.json"
1010
],
1111
"buildPresets": [
1212
{

cmake/CMakeDarwinPresets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"hidden": true,
1010
"cacheVariables": {
1111
"CMAKE_BUILD_TYPE": "Debug",
12-
"CMAKE_CXX_FLAGS": "-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined"
12+
"CMAKE_CXX_FLAGS": "-fsanitize=leak -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined"
1313
},
1414
"condition": {
1515
"type": "equals",

include/beman/execution26/detail/common.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define BEMAN_EXECUTION26_DELETE(msg) delete
1313
#endif
1414

15+
#define HAS_P3409
16+
1517
// ----------------------------------------------------------------------------
1618
/*!
1719
* \mainpage Asynchronous Operation Support
Lines changed: 195 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,209 @@
11
// include/beman/execution26/detail/finite_inplace_stop_source.hpp -*-C++-*-
2-
// ----------------------------------------------------------------------------
32
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4-
// ----------------------------------------------------------------------------
53

64
#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_FINITE_INPLACE_STOP_SOURCE
75
#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_FINITE_INPLACE_STOP_SOURCE
86

7+
#include <algorithm>
8+
#include <array>
9+
#include <atomic>
10+
#include <exception>
11+
#include <thread>
12+
#include <cstddef>
13+
14+
// ----------------------------------------------------------------------------
15+
16+
namespace beman::execution26::detail {
17+
struct finite_inplace_stop_callback_base {
18+
virtual auto notify() -> void = 0;
19+
};
20+
21+
struct finite_inplace_stop_marker_t
22+
: ::beman::execution26::detail::finite_inplace_stop_callback_base
23+
{
24+
auto notify() -> void override {}
25+
};
26+
inline constinit finite_inplace_stop_marker_t finite_inplace_stop_stopping{};
27+
inline constinit finite_inplace_stop_marker_t finite_inplace_stop_stopped{};
28+
}
29+
30+
namespace beman::execution26 {
31+
template <::std::size_t>
32+
class finite_inplace_stop_source;
33+
template <::std::size_t N, ::std::size_t I>
34+
requires(I < N)
35+
class finite_inplace_stop_token;
36+
template <::std::size_t N, ::std::size_t I, typename>
37+
requires(I < N)
38+
class finite_inplace_stop_callback;
39+
40+
template <::std::size_t N, ::std::size_t I, typename Callback>
41+
finite_inplace_stop_callback(finite_inplace_stop_token<N, I>, Callback)
42+
-> finite_inplace_stop_callback<N, I, Callback>;
43+
}
44+
45+
// ----------------------------------------------------------------------------
46+
47+
template <::std::size_t N, ::std::size_t I>
48+
requires(I < N)
49+
class beman::execution26::finite_inplace_stop_token
50+
{
51+
public:
52+
template <typename Callback>
53+
using callback_type = ::beman::execution26::finite_inplace_stop_callback<N, I, Callback>;
54+
55+
constexpr finite_inplace_stop_token() noexcept = default;
56+
57+
auto operator== (finite_inplace_stop_token const&) const noexcept -> bool = default;
58+
auto stop_possible() const noexcept -> bool { return this->source != nullptr; }
59+
auto stop_requested() const noexcept -> bool;
60+
auto swap(finite_inplace_stop_token&) noexcept -> void;
61+
62+
private:
63+
friend class ::beman::execution26::finite_inplace_stop_source<N>;
64+
template <std::size_t NN, std::size_t II, typename>
65+
requires(II < NN)
66+
friend class ::beman::execution26::finite_inplace_stop_callback;
67+
68+
finite_inplace_stop_token(::beman::execution26::finite_inplace_stop_source<N>* source)
69+
: source(source)
70+
{
71+
}
72+
::beman::execution26::finite_inplace_stop_source<N>* source{};
73+
};
74+
75+
// ----------------------------------------------------------------------------
76+
77+
template <std::size_t N>
78+
class beman::execution26::finite_inplace_stop_source
79+
{
80+
public:
81+
constexpr finite_inplace_stop_source() noexcept;
82+
finite_inplace_stop_source(finite_inplace_stop_source&&) = delete;
83+
finite_inplace_stop_source(finite_inplace_stop_source const&) = delete;
84+
~finite_inplace_stop_source() = default;
85+
auto operator=(finite_inplace_stop_source&&) -> finite_inplace_stop_source& = delete;
86+
auto operator=(finite_inplace_stop_source const&) -> finite_inplace_stop_source& = delete;
87+
88+
template <std::size_t I = N == 1? 0u: ~0u>
89+
requires (I < N)
90+
constexpr auto get_token() const noexcept
91+
-> beman::execution26::finite_inplace_stop_token<N, I>
92+
{
93+
return {const_cast<finite_inplace_stop_source*>(this)};
94+
}
95+
static constexpr auto stop_possible() noexcept -> bool { return true; }
96+
auto stop_requested() const noexcept -> bool;
97+
auto request_stop() noexcept -> bool;
98+
99+
private:
100+
template <::std::size_t NN, std::size_t II, typename>
101+
requires(II < NN)
102+
friend class ::beman::execution26::finite_inplace_stop_callback;
103+
104+
::std::atomic<bool> requested{false};
105+
::std::atomic<::std::thread::id> id;
106+
::std::array<::std::atomic<::beman::execution26::detail::finite_inplace_stop_callback_base*>, N> callbacks{};
107+
};
108+
109+
// ----------------------------------------------------------------------------
110+
111+
template <std::size_t N, std::size_t I, typename Callback>
112+
requires(I < N)
113+
class beman::execution26::finite_inplace_stop_callback
114+
: beman::execution26::detail::finite_inplace_stop_callback_base
115+
{
116+
public:
117+
template <typename Initializer>
118+
finite_inplace_stop_callback(::beman::execution26::finite_inplace_stop_token<N, I> token, Initializer&& init)
119+
: callback(init)
120+
, source(token.source)
121+
{
122+
::beman::execution26::detail::finite_inplace_stop_callback_base* expected{};
123+
124+
if (this->source && not this->source->callbacks[I].compare_exchange_strong(expected, this)) {
125+
if (expected == &::beman::execution26::detail::finite_inplace_stop_stopping
126+
|| expected == &::beman::execution26::detail::finite_inplace_stop_stopped) {
127+
this->source = nullptr;
128+
this->callback();
129+
}
130+
else {
131+
::std::terminate();
132+
}
133+
}
134+
}
135+
136+
finite_inplace_stop_callback(finite_inplace_stop_callback&&) = delete;
137+
finite_inplace_stop_callback(finite_inplace_stop_callback const&) = delete;
138+
~finite_inplace_stop_callback()
139+
{
140+
auto* const source{this->source};
141+
if (source) {
142+
auto result{source->callbacks[I].exchange(nullptr)};
143+
if (result == &::beman::execution26::detail::finite_inplace_stop_stopping
144+
&& source->id != ::std::this_thread::get_id()) {
145+
source->callbacks[I].wait(&::beman::execution26::detail::finite_inplace_stop_stopping);
146+
}
147+
}
148+
}
149+
auto operator=(finite_inplace_stop_callback&&) -> finite_inplace_stop_callback = delete;
150+
auto operator=(finite_inplace_stop_callback const&) -> finite_inplace_stop_callback = delete;
151+
152+
private:
153+
auto notify() -> void override {
154+
this->callback();
155+
}
156+
157+
Callback callback;
158+
::beman::execution26::finite_inplace_stop_source<N>* source;
159+
};
160+
161+
// ----------------------------------------------------------------------------
162+
163+
template <::std::size_t N, ::std::size_t I>
164+
requires(I < N)
165+
auto beman::execution26::finite_inplace_stop_token<N, I>::stop_requested() const noexcept -> bool
166+
{
167+
return this->source && this->source->stop_requested();
168+
}
169+
170+
template <::std::size_t N, ::std::size_t I>
171+
requires(I < N)
172+
auto beman::execution26::finite_inplace_stop_token<N, I>::swap(finite_inplace_stop_token& other) noexcept -> void
173+
{
174+
::std::swap(this->source, other.source);
175+
}
9176
// ----------------------------------------------------------------------------
10177

11-
namespace nstd {
12-
namespace xxx {
178+
template <::std::size_t N>
179+
constexpr beman::execution26::finite_inplace_stop_source<N>::finite_inplace_stop_source() noexcept
180+
{
181+
}
182+
183+
template <::std::size_t N>
184+
auto beman::execution26::finite_inplace_stop_source<N>::stop_requested() const noexcept -> bool
185+
{
186+
return this->requested;
187+
}
188+
189+
template <::std::size_t N>
190+
auto beman::execution26::finite_inplace_stop_source<N>::request_stop() noexcept -> bool
191+
{
192+
if (this->requested.exchange(true))
193+
return false;
194+
this->id = ::std::this_thread::get_id();
195+
for (auto& cb: this->callbacks) {
196+
auto current{cb.exchange(&::beman::execution26::detail::finite_inplace_stop_stopping)};
197+
if (current != nullptr) {
198+
current->notify();
199+
}
200+
cb = &::beman::execution26::detail::finite_inplace_stop_stopped;
201+
cb.notify_one();
13202
}
203+
return true;
14204
}
15205

16206
// ----------------------------------------------------------------------------
17207

208+
18209
#endif
Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,55 @@
11
// include/beman/execution26/detail/single_inplace_stop_token.hpp -*-C++-*-
2-
// ----------------------------------------------------------------------------
32
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4-
// ----------------------------------------------------------------------------
53

6-
#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_SINGLE_INPLACE_STOP_TOKEN
7-
#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_SINGLE_INPLACE_STOP_TOKEN
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SINGLE_INPLACE_STOP_TOKEN
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SINGLE_INPLACE_STOP_TOKEN
86

97
// ----------------------------------------------------------------------------
108

11-
namespace nstd {
12-
namespace xxx {
13-
}
9+
namespace beman::execution26 {
10+
template <typename Callback>
11+
class single_inplace_stop_callback;
12+
class single_inplace_stop_token;
13+
class single_inplace_stop_source;
1414
}
1515

1616
// ----------------------------------------------------------------------------
1717

18+
class beman::execution26::single_inplace_stop_token
19+
{
20+
public:
21+
template <typename Callback>
22+
using callback_type = ::beman::execution26::single_inplace_stop_callback<Callback>;
23+
24+
single_inplace_stop_token() = default;
25+
auto operator== (single_inplace_stop_token const&) const -> bool = default;
26+
auto stop_requested() const noexcept -> bool;
27+
auto stop_possible() const noexcept -> bool;
28+
auto swap(single_inplace_stop_token&) noexcept -> void;
29+
30+
private:
31+
::beman::execution26::single_inplace_stop_source* source{};
32+
};
33+
34+
// ----------------------------------------------------------------------------
35+
36+
class beman::execution26::single_inplace_stop_source
37+
{
38+
public:
39+
constexpr single_inplace_stop_source() noexcept {}
40+
single_inplace_stop_source(single_inplace_stop_source&&) = delete;
41+
single_inplace_stop_source(single_inplace_stop_source const&) = delete;
42+
~single_inplace_stop_source();
43+
auto operator=(single_inplace_stop_source&&) -> single_inplace_stop_source& = delete;
44+
auto operator=(single_inplace_stop_source const&) -> single_inplace_stop_source& = delete;
45+
46+
constexpr auto get_token() const noexcept -> ::beman::execution26::single_inplace_stop_token;
47+
static constexpr auto stop_possible() noexcept -> bool { return true; }
48+
auto stop_requested() const noexcept -> bool;
49+
auto request_stop() noexcept -> bool;
50+
};
51+
52+
// ----------------------------------------------------------------------------
53+
54+
1855
#endif

include/beman/execution26/detail/stoppable_source.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_STOPPABLE_SOURCE
66

77
#include <beman/execution26/detail/stoppable_token.hpp>
8+
#include <beman/execution26/detail/common.hpp>
89
#include <concepts>
910

1011
// ----------------------------------------------------------------------------
1112

1213
namespace beman::execution26::detail {
1314
template <typename Source>
1415
concept stoppable_source = requires(Source& source, const Source& csource) {
16+
#if not defined(HAS_P3409)
1517
{ csource.get_token() } -> ::beman::execution26::stoppable_token;
18+
#endif
1619
{ csource.stop_possible() } noexcept -> ::std::same_as<bool>;
1720
{ csource.stop_requested() } noexcept -> ::std::same_as<bool>;
1821
{ source.request_stop() } -> ::std::same_as<bool>;

src/beman/execution26/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ target_sources(
6969
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/env_promise.hpp
7070
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/env_type.hpp
7171
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/error_types_of_t.hpp
72+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/finite_inplace_stop_source.hpp
7273
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/forward_like.hpp
7374
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/forwarding_query.hpp
7475
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/fwd_env.hpp
@@ -142,6 +143,7 @@ target_sources(
142143
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/set_value.hpp
143144
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/simple_allocator.hpp
144145
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/simple_counting_scope.hpp
146+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/single_inplace_stop_source.hpp
145147
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/single_sender.hpp
146148
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/single_sender_value_type.hpp
147149
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/start.hpp

tests/beman/execution26/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ endif()
1111
list(
1212
APPEND
1313
execution_tests
14+
stopcallback-finite.test
15+
stopcallback-finite-cons.test
16+
stopcallback-finite-general.test
17+
stoptoken-finite.test
18+
stoptoken-finite-general.test
19+
stoptoken-finite-mem.test
20+
stopsource-finite.test
21+
stopsource-finite-general.test
22+
stopsource-finite-cons.test
23+
stopsource-finite-mem.test
24+
stopsource-single.test
25+
stopsource-single-general.test
26+
stopsource-single-cons.test
27+
stopsource-single-mem.test
28+
stoptoken-single.test
29+
stoptoken-single-general.test
30+
stoptoken-single-mem.test
1431
notify.test
1532
exec-scounting.test
1633
exec-awaitable.test

tests/beman/execution26/include/test/common.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// tests/beman/execution26/include/test/common.hpp -*-C++-*-
2-
// ----------------------------------------------------------------------------
32
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4-
// ----------------------------------------------------------------------------
53

64
#ifndef INCLUDED_TESTS_BEMAN_EXECUTION26_INCLUDE_TEST_COMMON
75
#define INCLUDED_TESTS_BEMAN_EXECUTION26_INCLUDE_TEST_COMMON
86

97
// ----------------------------------------------------------------------------
108

11-
namespace nstd {
12-
namespace xxx {
9+
namespace test {
10+
template <typename Fun>
11+
auto kill_test(Fun&& ) {
12+
//-dk:TODO
1313
}
1414
}
1515

tests/beman/execution26/include/test/execution.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define INCLUDED_TEST_EXECUTION
66

77
#include <beman/execution26/stop_token.hpp>
8+
//-dk:TODO #include <test/common.hpp>
89
#include <concepts>
910
#include <cstddef>
1011

0 commit comments

Comments
 (0)