You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let's call it something like LocalContext for now. And let's make the simplification we're dealing with a unifex::task.
The basic requirements I am looking for are:
When 2 unrelated tasks interleave on the same executor, their LocalContexts are isolated from one another.
When there's a parent-child relationship between 2 tasks (e.g. taskA co_awaits on taskB), taskA's context is propagated onto taskB's contexts.
LocalContexts resources are managed by the containing tasks (i.e. they get destroyed when the underlying coroutine gets destroyed).
Python has ContextVars that is more or less what I describe above. It has the added advantage that it works also in cases where you need plain thread local storage.
I did a little bit of search some time ago, but didn't see anything in the works or being proposed.
The text was updated successfully, but these errors were encountered:
I have something cooked up that uses task's scheduler affinity to save/restore a context on reschedule. A sketch of the API looks like
template <class T> struct ContextVar {
T& get(); // Return the value assigned to this variable within the current context.
// Raise when no value is assigned to the currrent context
void set(T); // Assign the value to the current context.
};
static ContextVar<int> s_data;
task<int> inner() {
co_await some_io_operation();
co_return s_data.get();
}
task<void> outer(int i) {
s_data.set(i+1);
int value = co_await inner();
assert(value == i+1);
}
task<void> main_event_loop() {
async_scope scope;
while (optional<int> data = co_await read_data()) {
scope.spawn_on(ContextVarsScheduler{Context::copy()}, outer(*data));
}
co_await scope.complete();
}
If there's interest, I can share the entire implementation. The quirks/downsides to this approach are
If a child task re-schedules somewhere in the middle of a call chain, that coroutine and subsequently spawned grandchild tasks no longer participates in the ContextVars re-schedule.
Doesn't work with non-scheduler affine coroutines
Spawning with other types like async_scope require explicit code to propagate the ContextVars scheduler. This happens magically for free with task's scheduler affinity, but does not come for free with async_scope etc.
Requires composing the ContextVarsScheduler with the "real" scheduler (e.g., specific thread pool, manual_event_loop, or other). I have a ComposedScheduler(Schedulers...) scheduler that composes 2 or more schedulers into one.
Another thought would be to integrate this directly into the loops (e.g. manual_event_loop) themselves (as Python does), which avoids the downsides above.
Let's call it something like
LocalContext
for now. And let's make the simplification we're dealing with aunifex::task
.The basic requirements I am looking for are:
LocalContext
s are isolated from one another.co_await
s ontaskB
), taskA's context is propagated ontotaskB
's contexts.LocalContext
s resources are managed by the containing tasks (i.e. they get destroyed when the underlying coroutine gets destroyed).Python has ContextVars that is more or less what I describe above. It has the added advantage that it works also in cases where you need plain thread local storage.
I did a little bit of search some time ago, but didn't see anything in the works or being proposed.
The text was updated successfully, but these errors were encountered: