Skip to content

Commit c67d8cd

Browse files
authored
Merge pull request #289 from elbeno/fix-periodic-alt-domain
🐛 Fix `periodic` with `time_scheduler_factory`
2 parents 50d6d18 + ebbf61a commit c67d8cd

2 files changed

Lines changed: 55 additions & 27 deletions

File tree

include/async/schedulers/time_scheduler.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,16 @@ time_scheduler(D)
231231

232232
template <typename Domain = timer_mgr::default_domain,
233233
stdx::ct_string Name = "time_scheduler">
234-
constexpr auto time_scheduler_factory =
235-
[]<typename D>(D d) -> time_scheduler<Domain, Name, D> { return {d}; };
234+
constexpr auto time_scheduler_factory = []<typename... Ds>
235+
requires(sizeof...(Ds) <= 1u)
236+
(Ds... ds) {
237+
if constexpr (sizeof...(Ds) == 0) {
238+
return time_scheduler<Domain, Name, detail::no_duration_t,
239+
detail::no_task_t>{};
240+
} else {
241+
return time_scheduler<Domain, Name, Ds...>{ds...};
242+
}
243+
};
236244

237245
struct time_scheduler_sender_t;
238246

test/periodic.cpp

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,8 @@ TEST_CASE("periodic_n advertises what it sends", "[periodic]") {
117117

118118
TEST_CASE("periodic repeats periodically", "[periodic]") {
119119
int var{};
120-
[[maybe_unused]] auto s =
121-
async::time_scheduler{}.schedule() | async::then([&] { ++var; }) |
122-
async::periodic_until(1s, [&] { return var == 2; });
120+
auto s = async::time_scheduler{}.schedule() | async::then([&] { ++var; }) |
121+
async::periodic_until(1s, [&] { return var == 2; });
123122
auto op = async::connect(s, receiver{[&] { var = 42; }});
124123
async::start(op);
125124
CHECK(enabled<default_domain>);
@@ -134,9 +133,8 @@ TEST_CASE("periodic repeats periodically", "[periodic]") {
134133

135134
TEST_CASE("periodic_until terse form", "[periodic]") {
136135
int var{};
137-
[[maybe_unused]] auto s = async::time_scheduler{}.schedule() |
138-
async::then([&] { return ++var; }) |
139-
async::periodic_until(1s, 2);
136+
auto s = async::time_scheduler{}.schedule() |
137+
async::then([&] { return ++var; }) | async::periodic_until(1s, 2);
140138
auto op = async::connect(s, receiver{[&](auto) { var = 42; }});
141139
async::start(op);
142140
CHECK(enabled<default_domain>);
@@ -151,11 +149,10 @@ TEST_CASE("periodic_until terse form", "[periodic]") {
151149

152150
TEST_CASE("periodic allows continue_on another scheduler", "[periodic]") {
153151
int var{};
154-
[[maybe_unused]] auto s =
155-
async::time_scheduler{}.schedule() |
156-
async::continue_on(async::fixed_priority_scheduler<0>{}) |
157-
async::then([&] { ++var; }) |
158-
async::periodic_until(1s, [&] { return var == 2; });
152+
auto s = async::time_scheduler{}.schedule() |
153+
async::continue_on(async::fixed_priority_scheduler<0>{}) |
154+
async::then([&] { ++var; }) |
155+
async::periodic_until(1s, [&] { return var == 2; });
159156
auto op = async::connect(s, receiver{[&] { var = 42; }});
160157
async::start(op);
161158
CHECK(enabled<default_domain>);
@@ -173,9 +170,8 @@ TEST_CASE("periodic allows continue_on another scheduler", "[periodic]") {
173170

174171
TEST_CASE("periodic_n repeats n times", "[periodic]") {
175172
int var{};
176-
[[maybe_unused]] auto s = async::time_scheduler{}.schedule() |
177-
async::then([&] { ++var; }) |
178-
async::periodic_n(1s, 2);
173+
auto s = async::time_scheduler{}.schedule() | async::then([&] { ++var; }) |
174+
async::periodic_n(1s, 2);
179175
auto op = async::connect(s, receiver{[&] { var = 42; }});
180176
async::start(op);
181177
CHECK(enabled<default_domain>);
@@ -195,8 +191,8 @@ TEST_CASE("periodic can be cancelled", "[periodic]") {
195191
int var{};
196192
stoppable_receiver r{[&] { var += 42; }};
197193

198-
[[maybe_unused]] auto s = async::time_scheduler{}.schedule() |
199-
async::then([&] { ++var; }) | async::periodic(1s);
194+
auto s = async::time_scheduler{}.schedule() | async::then([&] { ++var; }) |
195+
async::periodic(1s);
200196
auto op = async::connect(s, r);
201197
async::start(op);
202198
async::timer_mgr::service_task();
@@ -215,8 +211,7 @@ TEST_CASE("periodic sets the correct first expiration time", "[periodic]") {
215211
using hal_t = timer_hal<default_domain>;
216212
using TP = typename hal_t::time_point_t;
217213

218-
[[maybe_unused]] auto s =
219-
async::time_scheduler{}.schedule() | async::periodic(1s);
214+
auto s = async::time_scheduler{}.schedule() | async::periodic(1s);
220215
auto op = async::connect(s, r);
221216

222217
current_time<default_domain, TP> = TP{1s};
@@ -240,8 +235,7 @@ TEST_CASE("periodic sets the nth expiration time without drift", "[periodic]") {
240235
using hal_t = timer_hal<default_domain>;
241236
using TP = typename hal_t::time_point_t;
242237

243-
[[maybe_unused]] auto s =
244-
async::time_scheduler{}.schedule() | async::periodic(1s);
238+
auto s = async::time_scheduler{}.schedule() | async::periodic(1s);
245239
auto op = async::connect(s, r);
246240

247241
current_time<default_domain, TP> = TP{1s};
@@ -271,8 +265,7 @@ TEST_CASE("periodic sets the nth expiration time safely", "[periodic]") {
271265
using hal_t = timer_hal<default_domain>;
272266
using TP = typename hal_t::time_point_t;
273267

274-
[[maybe_unused]] auto s =
275-
async::time_scheduler{}.schedule() | async::periodic(1s);
268+
auto s = async::time_scheduler{}.schedule() | async::periodic(1s);
276269
auto op = async::connect(s, r);
277270

278271
current_time<default_domain, TP> = TP{1s};
@@ -342,9 +335,8 @@ TEST_CASE("periodic can be parameterized with a quantized provider",
342335
using hal_t = timer_hal<default_domain>;
343336
using TP = typename hal_t::time_point_t;
344337

345-
[[maybe_unused]] auto s =
346-
async::time_scheduler{}.schedule() |
347-
async::periodic<"", async::safe_quantized_expiry>(1s);
338+
auto s = async::time_scheduler{}.schedule() |
339+
async::periodic<"", async::safe_quantized_expiry>(1s);
348340
auto op = async::connect(s, r);
349341

350342
current_time<default_domain, TP> = TP{1s};
@@ -442,3 +434,31 @@ TEST_CASE("periodic can be named and debugged", "[periodic]") {
442434
CHECK(debug_events == std::vector{"op periodic_name start"s,
443435
"op periodic_name set_stopped"s});
444436
}
437+
438+
namespace {
439+
struct alt_domain;
440+
using alt_timer_manager_t = async::generic_timer_manager<timer_hal<alt_domain>>;
441+
} // namespace
442+
template <>
443+
[[maybe_unused]] inline auto async::injected_timer_manager<alt_domain> =
444+
alt_timer_manager_t{};
445+
446+
TEST_CASE("periodic repeats periodically (different domain)", "[periodic]") {
447+
enabled<default_domain> = false;
448+
int var{};
449+
auto scheduler_factory = async::time_scheduler_factory<alt_domain>;
450+
451+
auto s = scheduler_factory().schedule() | async::then([&] { ++var; }) |
452+
async::periodic_until(1s, [&] { return var == 2; });
453+
[[maybe_unused]] auto op = async::connect(s, receiver{[&] { var = 42; }});
454+
async::start(op);
455+
CHECK(enabled<alt_domain>);
456+
CHECK(not enabled<default_domain>);
457+
CHECK(not async::timer_mgr::is_idle<alt_domain>());
458+
async::timer_mgr::service_task<alt_domain>();
459+
CHECK(var == 1);
460+
CHECK(not async::timer_mgr::is_idle<alt_domain>());
461+
async::timer_mgr::service_task<alt_domain>();
462+
CHECK(async::timer_mgr::is_idle<alt_domain>());
463+
CHECK(var == 42);
464+
}

0 commit comments

Comments
 (0)