Skip to content

Commit

Permalink
Merge pull request #1455 from lucteo/get-system-scheduler-api
Browse files Browse the repository at this point in the history
Use `get_system_scheduler()` to obtain the system scheduler.
  • Loading branch information
ericniebler authored Dec 29, 2024
2 parents ac27beb + 533ee60 commit e6fb836
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 90 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
build*/
.build*/
.cache
.vscode/*
!.vscode/launch.json
Expand Down
39 changes: 6 additions & 33 deletions include/exec/system_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,8 @@ namespace exec {
template <stdexec::sender _S, std::integral _Size, class _Fn>
class system_bulk_sender;

/// Provides a view on some global underlying execution context supporting parallel forward progress.
class system_context {
public:
/// Initializes the system context with the default implementation.
system_context();
~system_context() = default;

system_context(const system_context&) = delete;
system_context(system_context&&) = delete;
system_context& operator=(const system_context&) = delete;
system_context& operator=(system_context&&) = delete;

// Returns a scheduler that can add work to the underlying execution context.
system_scheduler get_scheduler();

/// Returns the maximum number of threads the context may support; this is just a hint.
size_t max_concurrency() const noexcept;

private:
/// The actual implementation of the system context.
system_context_replaceability::system_scheduler* __impl_{nullptr};
};
/// Returns a scheduler that can add work to the underlying execution context.
system_scheduler get_system_scheduler();

/// The execution domain of the system_scheduler, used for the purposes of customizing
/// sender algorithms such as `bulk`.
Expand Down Expand Up @@ -540,20 +520,13 @@ namespace exec {
_Fn __fun_;
};

inline system_context::system_context() {
__impl_ = system_context_replaceability::query_system_context<
inline system_scheduler get_system_scheduler() {
auto __impl = system_context_replaceability::query_system_context<
system_context_replaceability::system_scheduler>();
if (!__impl_) {
if (!__impl) {
throw std::runtime_error{"No system context implementation found"};
}
}

inline system_scheduler system_context::get_scheduler() {
return system_scheduler{__impl_};
}

inline size_t system_context::max_concurrency() const noexcept {
return std::thread::hardware_concurrency();
return system_scheduler{__impl};
}

inline auto system_scheduler::query(stdexec::get_forward_progress_guarantee_t) const noexcept
Expand Down
72 changes: 17 additions & 55 deletions test/exec/test_system_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,70 +33,41 @@

namespace ex = stdexec;

TEST_CASE("system_context has default ctor and dtor", "[types][system_scheduler]") {
STATIC_REQUIRE(std::is_default_constructible_v<exec::system_context>);
STATIC_REQUIRE(std::is_destructible_v<exec::system_context>);
}

TEST_CASE("system_context is not copyable nor movable", "[types][system_scheduler]") {
STATIC_REQUIRE_FALSE(std::is_copy_constructible_v<exec::system_context>);
STATIC_REQUIRE_FALSE(std::is_move_constructible_v<exec::system_context>);
}

TEST_CASE("system_context can return a scheduler", "[types][system_scheduler]") {
auto sched = exec::system_context{}.get_scheduler();
auto sched = exec::get_system_scheduler();
STATIC_REQUIRE(ex::scheduler<decltype(sched)>);
}

TEST_CASE("can query max concurrency from system_context", "[types][system_scheduler]") {
exec::system_context ctx;
size_t max_concurrency = ctx.max_concurrency();
REQUIRE(max_concurrency >= 1);
}

TEST_CASE("system scheduler is not default constructible", "[types][system_scheduler]") {
auto sched = exec::system_context{}.get_scheduler();
auto sched = exec::get_system_scheduler();
using sched_t = decltype(sched);
STATIC_REQUIRE(!std::is_default_constructible_v<sched_t>);
STATIC_REQUIRE(std::is_destructible_v<sched_t>);
}

TEST_CASE("system scheduler is copyable and movable", "[types][system_scheduler]") {
auto sched = exec::system_context{}.get_scheduler();
auto sched = exec::get_system_scheduler();
using sched_t = decltype(sched);
STATIC_REQUIRE(std::is_copy_constructible_v<sched_t>);
STATIC_REQUIRE(std::is_move_constructible_v<sched_t>);
}

TEST_CASE("a copied scheduler is equal to the original", "[types][system_scheduler]") {
exec::system_context ctx;
auto sched1 = ctx.get_scheduler();
auto sched1 = exec::get_system_scheduler();
auto sched2 = sched1;
REQUIRE(sched1 == sched2);
}

TEST_CASE(
"two schedulers obtained from the same system_context are equal",
"[types][system_scheduler]") {
exec::system_context ctx;
auto sched1 = ctx.get_scheduler();
auto sched2 = ctx.get_scheduler();
REQUIRE(sched1 == sched2);
}

TEST_CASE(
"compare two schedulers obtained from different system_context objects",
"two schedulers obtained from get_system_scheduler() are equal",
"[types][system_scheduler]") {
exec::system_context ctx1;
auto sched1 = ctx1.get_scheduler();
exec::system_context ctx2;
auto sched2 = ctx2.get_scheduler();
// TODO: clarify the result of this in the paper
auto sched1 = exec::get_system_scheduler();
auto sched2 = exec::get_system_scheduler();
REQUIRE(sched1 == sched2);
}

TEST_CASE("system scheduler can produce a sender", "[types][system_scheduler]") {
auto snd = ex::schedule(exec::system_context{}.get_scheduler());
auto snd = ex::schedule(exec::get_system_scheduler());
using sender_t = decltype(snd);

STATIC_REQUIRE(ex::sender<sender_t>);
Expand All @@ -105,17 +76,15 @@ TEST_CASE("system scheduler can produce a sender", "[types][system_scheduler]")
}

TEST_CASE("trivial schedule task on system context", "[types][system_scheduler]") {
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

ex::sync_wait(ex::schedule(sched));
}

TEST_CASE("simple schedule task on system context", "[types][system_scheduler]") {
std::thread::id this_id = std::this_thread::get_id();
std::thread::id pool_id{};
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto snd = ex::then(ex::schedule(sched), [&] { pool_id = std::this_thread::get_id(); });

Expand All @@ -127,14 +96,12 @@ TEST_CASE("simple schedule task on system context", "[types][system_scheduler]")
}

TEST_CASE("simple schedule forward progress guarantee", "[types][system_scheduler]") {
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();
REQUIRE(ex::get_forward_progress_guarantee(sched) == ex::forward_progress_guarantee::parallel);
}

TEST_CASE("get_completion_scheduler", "[types][system_scheduler]") {
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();
REQUIRE(ex::get_completion_scheduler<ex::set_value_t>(ex::get_env(ex::schedule(sched))) == sched);
REQUIRE(
ex::get_completion_scheduler<ex::set_stopped_t>(ex::get_env(ex::schedule(sched))) == sched);
Expand All @@ -144,8 +111,7 @@ TEST_CASE("simple chain task on system context", "[types][system_scheduler]") {
std::thread::id this_id = std::this_thread::get_id();
std::thread::id pool_id{};
std::thread::id pool_id2{};
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto snd = ex::then(ex::schedule(sched), [&] { pool_id = std::this_thread::get_id(); });
auto snd2 = ex::then(std::move(snd), [&] { pool_id2 = std::this_thread::get_id(); });
Expand All @@ -161,8 +127,7 @@ TEST_CASE("simple chain task on system context", "[types][system_scheduler]") {

// TODO: fix this test. This also makes tsan and asan unhappy.
// TEST_CASE("checks stop_token before starting the work", "[types][system_scheduler]") {
// exec::system_context ctx;
// exec::system_scheduler sched = ctx.get_scheduler();
// exec::system_scheduler sched = exec::get_system_scheduler();

// exec::async_scope scope;
// scope.request_stop();
Expand All @@ -185,8 +150,7 @@ TEST_CASE("simple bulk task on system context", "[types][system_scheduler]") {
std::thread::id this_id = std::this_thread::get_id();
constexpr size_t num_tasks = 16;
std::thread::id pool_ids[num_tasks];
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto bulk_snd = ex::bulk(ex::schedule(sched), num_tasks, [&](unsigned long id) {
pool_ids[id] = std::this_thread::get_id();
Expand All @@ -207,8 +171,7 @@ TEST_CASE("simple bulk chaining on system context", "[types][system_scheduler]")
std::thread::id pool_id{};
std::thread::id propagated_pool_ids[num_tasks];
std::thread::id pool_ids[num_tasks];
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto snd = ex::then(ex::schedule(sched), [&] {
pool_id = std::this_thread::get_id();
Expand Down Expand Up @@ -268,8 +231,7 @@ TEST_CASE("can change the implementation of system context", "[types][system_sch

std::thread::id this_id = std::this_thread::get_id();
std::thread::id pool_id{};
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto snd = ex::then(ex::schedule(sched), [&] { pool_id = std::this_thread::get_id(); });

Expand Down
3 changes: 1 addition & 2 deletions test/exec/test_system_context_replaceability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ TEST_CASE(
"[system_scheduler][replaceability]") {
std::thread::id this_id = std::this_thread::get_id();
std::thread::id pool_id{};
exec::system_context ctx;
exec::system_scheduler sched = ctx.get_scheduler();
exec::system_scheduler sched = exec::get_system_scheduler();

auto snd = ex::then(ex::schedule(sched), [&] { pool_id = std::this_thread::get_id(); });

Expand Down

0 comments on commit e6fb836

Please sign in to comment.