scope: pass around the scheduler
The latest stdexec requires task's which co-await to be able to
get the scheduler of the receiver. This in turn requires our
scope implementation to have the scheduler it was originally
created under (which is the run_loop). Modify context/scope so that
the `run_loop&` is given to the scope constructor and add the
appropriate tag_invoke to get the scheduler from the scope.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: Ie49ffd66feb80922e7a42b7922d67bf38006551e
diff --git a/include/sdbusplus/async/context.hpp b/include/sdbusplus/async/context.hpp
index 552d74a..17a8a37 100644
--- a/include/sdbusplus/async/context.hpp
+++ b/include/sdbusplus/async/context.hpp
@@ -90,7 +90,6 @@
bus_t bus;
event_source_t dbus_source;
event_t event_loop{};
- scope pending_tasks{};
/** The async run-loop from std::execution. */
execution::run_loop loop{};
@@ -99,10 +98,11 @@
/** Stop source */
std::stop_source initial_stop{};
+ scope pending_tasks{loop};
// In order to coordinate final completion of work, we keep some tasks
// on a separate scope (the ones which maintain the sd-event/dbus state
// and keep a final stop-source for them.
- scope internal_tasks{};
+ scope internal_tasks{loop};
std::stop_source final_stop{};
// Lock and condition variable to signal `caller`.
diff --git a/include/sdbusplus/async/scope.hpp b/include/sdbusplus/async/scope.hpp
index c7db3e6..6fc21f6 100644
--- a/include/sdbusplus/async/scope.hpp
+++ b/include/sdbusplus/async/scope.hpp
@@ -34,7 +34,8 @@
*/
struct scope
{
- scope() = default;
+ scope() = delete;
+ explicit scope(execution::run_loop& loop) : loop(loop) {}
// The scope destructor can throw if it was destructed while there are
// outstanding tasks.
@@ -64,6 +65,8 @@
size_t pending_count = 0;
std::deque<std::exception_ptr> pending_exceptions = {};
scope_ns::scope_completion* pending = nullptr;
+
+ execution::run_loop& loop;
};
namespace scope_ns
@@ -101,10 +104,22 @@
return self;
}
+ friend decltype(auto) tag_invoke(execution::get_scheduler_t,
+ const scope_receiver& self) noexcept
+ {
+ return self.get_scheduler();
+ }
+
void complete(std::exception_ptr&& = {}) noexcept;
void* op_state;
scope* s = nullptr;
+
+ private:
+ decltype(auto) get_scheduler() const
+ {
+ return s->loop.get_scheduler();
+ }
};
/** The holder of the connect operational-state. */