Skip to content

Commit 01f4bf2

Browse files
committed
added schedule and scheduler (and starts on a few other components)
1 parent 62853a5 commit 01f4bf2

9 files changed

+324
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// include/Beman/Execution26/detail/almost_scheduler.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_ALMOST_SCHEDULER
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_ALMOST_SCHEDULER
6+
7+
#include <Beman/Execution26/detail/queryable.hpp>
8+
#include <Beman/Execution26/detail/schedule.hpp>
9+
#include <Beman/Execution26/detail/sender.hpp>
10+
#include <concepts>
11+
#include <utility>
12+
13+
// ----------------------------------------------------------------------------
14+
15+
namespace Beman::Execution26
16+
{
17+
struct scheduler_t {};
18+
}
19+
20+
namespace Beman::Execution26::Detail
21+
{
22+
template <typename Scheduler>
23+
concept almost_scheduler
24+
= ::std::derived_from<typename ::std::remove_cvref_t<Scheduler>::scheduler_concept,
25+
::Beman::Execution26::scheduler_t>
26+
&& ::Beman::Execution26::Detail::queryable<Scheduler>
27+
&& requires(Scheduler&& sched) {
28+
{ ::Beman::Execution26::schedule(::std::forward<Scheduler>(sched)) }
29+
-> ::Beman::Execution26::sender;
30+
}
31+
&& ::std::equality_comparable<::std::remove_cvref_t<Scheduler>>
32+
&& ::std::copy_constructible<::std::remove_cvref_t<Scheduler>>
33+
;
34+
}
35+
36+
// ----------------------------------------------------------------------------
37+
38+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// include/Beman/Execution26/detail/completion_domain.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_DOMAIN
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_DOMAIN
6+
7+
#include <Beman/Execution26/detail/default_domain.hpp>
8+
9+
// ----------------------------------------------------------------------------
10+
11+
namespace Beman::Execution26::Detail
12+
{
13+
template <typename Default = ::Beman::Execution26::default_domain, typename Sender>
14+
constexpr auto completion_domain(Sender const&) noexcept
15+
{
16+
//-dk:TODO
17+
}
18+
}
19+
20+
// ----------------------------------------------------------------------------
21+
22+
#endif

include/Beman/Execution26/detail/get_domain_late.hpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,37 @@
44
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE
55
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE
66

7-
// #include <Beman/Execution26/detail/continues_on.hpp>
87
#include <Beman/Execution26/detail/default_domain.hpp>
8+
#include <Beman/Execution26/detail/completion_domain.hpp>
9+
#include <Beman/Execution26/detail/get_env.hpp>
10+
#include <Beman/Execution26/detail/get_domain.hpp>
11+
#include <Beman/Execution26/detail/get_scheduler.hpp>
912
#include <Beman/Execution26/detail/sender_decompose.hpp>
13+
#include <concepts>
1014

1115
// ----------------------------------------------------------------------------
1216

1317
namespace Beman::Execution26::Detail
1418
{
19+
template <typename T>
20+
concept not_void = not ::std::same_as<T, void>;
21+
1522
template <typename Tag>
1623
struct get_domain_late_helper
1724
{
1825
template <typename Sender, typename Env>
1926
static constexpr auto get(Sender const& sender, Env const& env) noexcept
2027
{
21-
(void)sender; (void)env;
22-
return ::Beman::Execution26::default_domain();
28+
if constexpr (requires{ { ::Beman::Execution26::get_domain(::Beman::Execution26::get_env(sender)) } -> ::Beman::Execution26::Detail::not_void; })
29+
return ::Beman::Execution26::get_domain(::Beman::Execution26::get_env(sender));
30+
else if constexpr (requires{ { ::Beman::Execution26::Detail::completion_domain<void>(sender) } -> ::Beman::Execution26::Detail::not_void; })
31+
return ::Beman::Execution26::Detail::completion_domain<void>(sender);
32+
else if constexpr (requires{ { ::Beman::Execution26::get_domain(env) } -> ::Beman::Execution26::Detail::not_void; })
33+
return ::Beman::Execution26::get_domain(env);
34+
else if constexpr (requires{ { ::Beman::Execution26::get_domain(::Beman::Execution26::get_scheduler(env)) } -> ::Beman::Execution26::Detail::not_void; })
35+
return ::Beman::Execution26::get_domain(::Beman::Execution26::get_scheduler(env));
36+
else
37+
return ::Beman::Execution26::default_domain();
2338
}
2439
};
2540
template <typename Sender, typename Env>

include/Beman/Execution26/detail/get_scheduler.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ namespace Beman::Execution26
1515
: ::Beman::Execution26::forwarding_query_t
1616
{
1717
template <typename Env>
18+
requires requires(get_scheduler_t const& self, Env&& env)
19+
{
20+
::std::as_const(env).query(self);
21+
22+
}
1823
auto operator()(Env&& env) const noexcept
1924
{
2025
static_assert(noexcept(::std::as_const(env).query(*this)));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// include/Beman/Execution26/detail/schedule.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE
6+
7+
#include <Beman/Execution26/detail/sender.hpp>
8+
#include <Beman/Execution26/detail/common.hpp>
9+
#include <utility>
10+
11+
// ----------------------------------------------------------------------------
12+
13+
namespace Beman::Execution26
14+
{
15+
struct schedule_t
16+
{
17+
template <typename Scheduler>
18+
requires (not requires(Scheduler&& sched)
19+
{
20+
{ ::std::forward<Scheduler>(sched).schedule() }
21+
-> ::Beman::Execution26::sender;
22+
})
23+
auto operator()(Scheduler&& sched) const
24+
= BEMAN_EXECUTION26_DELETE("the scheduler needs a schedule() member returning a sender");
25+
26+
template <typename Scheduler>
27+
requires requires(Scheduler&& sched)
28+
{
29+
{ ::std::forward<Scheduler>(sched).schedule() }
30+
-> ::Beman::Execution26::sender;
31+
}
32+
auto operator()(Scheduler&& sched) const
33+
noexcept(noexcept(std::forward<Scheduler>(sched).schedule()))
34+
{
35+
return std::forward<Scheduler>(sched).schedule();
36+
}
37+
};
38+
39+
inline constexpr ::Beman::Execution26::schedule_t schedule{};
40+
}
41+
42+
// ----------------------------------------------------------------------------
43+
44+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// include/Beman/Execution26/detail/scheduler.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULER
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULER
6+
7+
#include <Beman/Execution26/detail/almost_scheduler.hpp>
8+
#include <Beman/Execution26/detail/get_completion_scheduler.hpp>
9+
#include <Beman/Execution26/detail/get_env.hpp>
10+
#include <Beman/Execution26/detail/schedule.hpp>
11+
#include <Beman/Execution26/detail/set_value.hpp>
12+
#include <concepts>
13+
#include <type_traits>
14+
15+
// ----------------------------------------------------------------------------
16+
17+
namespace Beman::Execution26
18+
{
19+
template <typename Scheduler>
20+
concept scheduler
21+
= ::Beman::Execution26::Detail::almost_scheduler<Scheduler>
22+
&& requires(Scheduler&& sched) {
23+
{
24+
auto(::Beman::Execution26::get_completion_scheduler<::Beman::Execution26::set_value_t>(
25+
::Beman::Execution26::get_env(
26+
::Beman::Execution26::schedule(
27+
::std::forward<Scheduler>(sched)
28+
)
29+
)
30+
))
31+
} -> ::std::same_as<::std::remove_cvref_t<Scheduler>>;
32+
}
33+
;
34+
}
35+
36+
// ----------------------------------------------------------------------------
37+
38+
#endif

src/Beman/Execution26/tests/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

44
list(APPEND execution_tests
5+
exec-sched.pass
6+
exec-schedule.pass
57
exec-domain-default.pass
68
exec-get-scheduler.pass
79
exec-get-compl-sched.pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// src/Beman/Execution26/tests/exec-sched.pass.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <Beman/Execution26/detail/scheduler.hpp>
5+
#include <test/execution.hpp>
6+
7+
// ----------------------------------------------------------------------------
8+
9+
namespace
10+
{
11+
struct bad_env
12+
{
13+
auto query(test_std::get_completion_scheduler_t<test_std::set_value_t> const&) const noexcept
14+
{
15+
return 0;
16+
}
17+
};
18+
19+
template <typename Scheduler>
20+
struct env
21+
{
22+
auto query(test_std::get_completion_scheduler_t<test_std::set_value_t> const&) const noexcept
23+
{
24+
return Scheduler{};
25+
}
26+
};
27+
28+
template <typename Env>
29+
struct sender
30+
{
31+
using sender_concept = test_std::sender_t;
32+
auto get_env() const noexcept { return Env{}; }
33+
};
34+
35+
struct no_scheduler_concept
36+
{
37+
auto schedule() -> sender<env<no_scheduler_concept>> { return {}; }
38+
auto operator== (no_scheduler_concept const&) const -> bool = default;
39+
};
40+
41+
struct not_queryable
42+
{
43+
using scheduler_concept = test_std::scheduler_t;
44+
~not_queryable() = delete;
45+
auto schedule() -> sender<env<not_queryable>> { return {}; }
46+
auto operator== (not_queryable const&) const -> bool = default;
47+
};
48+
49+
struct no_schedule
50+
{
51+
using scheduler_concept = test_std::scheduler_t;
52+
auto operator== (no_schedule const&) const -> bool = default;
53+
};
54+
55+
struct not_equality_comparable
56+
{
57+
using scheduler_concept = test_std::scheduler_t;
58+
auto schedule() -> sender<env<not_equality_comparable>> { return {}; }
59+
};
60+
61+
struct not_copy_constructible
62+
{
63+
using scheduler_concept = test_std::scheduler_t;
64+
not_copy_constructible(not_copy_constructible const&) = delete;
65+
auto schedule() -> sender<env<not_copy_constructible>> { return {}; }
66+
auto operator== (not_copy_constructible const&) const -> bool = default;
67+
};
68+
69+
struct scheduler
70+
{
71+
using scheduler_concept = test_std::scheduler_t;
72+
auto schedule() -> sender<env<scheduler>> { return {}; }
73+
auto operator== (scheduler const&) const -> bool = default;
74+
};
75+
76+
struct bad_completion_scheduler
77+
{
78+
using scheduler_concept = test_std::scheduler_t;
79+
auto schedule() -> sender<env<scheduler>> { return {}; }
80+
auto operator== (bad_completion_scheduler const&) const -> bool = default;
81+
};
82+
}
83+
84+
auto main() -> int
85+
{
86+
static_assert(test_std::sender<sender<env<scheduler>>>);
87+
static_assert(std::same_as<env<scheduler>, decltype(test_std::get_env(sender<env<scheduler>>{}))>);
88+
static_assert(std::same_as<int, decltype(test_std::get_completion_scheduler<test_std::set_value_t>(bad_env{}))>);
89+
90+
static_assert(not test_std::scheduler<int>);
91+
static_assert(not test_std::scheduler<no_scheduler_concept>);
92+
static_assert(not test_std::scheduler<not_queryable>);
93+
static_assert(not test_std::scheduler<no_schedule>);
94+
static_assert(not test_std::scheduler<not_equality_comparable>);
95+
static_assert(not test_std::scheduler<not_copy_constructible>);
96+
static_assert(not test_std::scheduler<bad_completion_scheduler>);
97+
static_assert(test_std::scheduler<scheduler>);
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// src/Beman/Execution26/tests/exec-schedule.pass.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <Beman/Execution26/detail/schedule.hpp>
5+
#include <test/execution.hpp>
6+
#include <concepts>
7+
#include <utility>
8+
9+
// ----------------------------------------------------------------------------
10+
11+
namespace
12+
{
13+
struct non_scheduler
14+
{
15+
};
16+
17+
struct sender
18+
{
19+
using sender_concept = test_std::sender_t;
20+
int value{};
21+
auto operator== (sender const&) const -> bool = default;
22+
};
23+
24+
template <bool Noexcept, typename Sender>
25+
struct scheduler
26+
{
27+
int value{};
28+
auto schedule() noexcept(Noexcept) { return Sender{this->value}; }
29+
};
30+
31+
struct rvalue_scheduler
32+
{
33+
int value{};
34+
auto schedule() && noexcept { return sender{this->value}; }
35+
};
36+
37+
template <bool Expect, typename Scheduler>
38+
auto test_schedule(Scheduler&& sched)
39+
{
40+
static_assert(Expect == requires{ test_std::schedule(::std::forward<Scheduler>(sched)); });
41+
if constexpr (Expect)
42+
{
43+
static_assert(noexcept(test_std::schedule(std::forward<Scheduler>(sched))) == noexcept(std::forward<Scheduler>(sched).schedule()));
44+
auto s = test_std::schedule(std::forward<Scheduler>(sched));
45+
assert(s.value == sched.value);
46+
}
47+
}
48+
}
49+
50+
auto main() -> int
51+
{
52+
static_assert(std::same_as<test_std::schedule_t const, decltype(test_std::schedule)>);
53+
static_assert(test_std::sender<sender>);
54+
test_schedule<false>(non_scheduler{});
55+
test_schedule<false>(scheduler<true, int>{17});
56+
test_schedule<true>(scheduler<false, sender>{17});
57+
test_schedule<true>(scheduler<true, sender>{17});
58+
test_schedule<true>(rvalue_scheduler{17});
59+
}

0 commit comments

Comments
 (0)