Replies: 1 comment
-
To give some context to how I came to this design. I was poking around at the redesign for app states using side effect subgraphs. There were a lot of issues and structured concurrency cleaned things up in a very neat and tidy way.
Not sure if this was everything, but it's at least what I could reconstruct from my notes. |
Beta Was this translation helpful? Give feedback.
-
Structured Concurrency for User Controlled Scheduling
Made this a discussion instead of an rfc as this doesn't feel very scoped and has a lot of open design questions.
Motivation
This is a discussion to add some support for structured concurrency in Bevy. The main new feature is to add the ability to run schedules from inside of a system from a scope. This allows for scopes to be nested and is a main feature of structured concurrency.
Systems are the base unit of concurrency inside of Bevy. By allowing running a schedule inside of a system, we have the basics of structured concurrency, where scopes nested inside other scopes must be completed before the outer scope is completed. Structured concurrency makes it easier to reason about how tasks are being run. This should allow building better abstractions for Application State and Stages and give power to users to create their own scheduling abstractions.
Also now that schedules are run from a system other systems can be scheduled around the schedule running system with before and after labeling.
Running schedules from scopes
For this discussion we define a schedule to be a group of systems that are topologically ordered with before and after labeling. They will need to be run from inside of an async scope inside of an async system.
Examples for AppState and Stages
We can use the structured concurrency primitives to build things like stages and app state. These examples are not full designs, but rough code to suggest what can be accomplished with the new scheduling primitives.
AppState
App State is essentially a group of schedules with some sugar for lifecycle events. In this model a state is directly tied to the systems that run in that state.
Stages
Stages are a ordered list of schedules.
New Features Needed
Running a schedule from a system would require a decent number of new features. The features required are listed below, but do not have a concrete design.
Async scopes and async systems
We need async scopes and async systems so we can release the thread the system is running on while running the schedule.
A common executor or a shared data access struct
Systems running in different scopes need to coordinate so they don't have conflicting data accesses. This is currently done in the parallel executor of a stage. This logic would need to be lifted into an executor shared by all scopes or we could create a shared data access struct that each system would need to access before running. The shared struct would probably require a mutex or rwlock, but might lead to cleaner code. Would need to experiment. The schedules also need to coordinate running exclusive systems which would probably be done through access conflicts.
Shared Task Pool
The ComputeTaskPool needs to be shared by all scheduling systems without blocking other scheduling systems from running. The current implementation does not allow this.
Data owned by the schedule
Things like schedules cannot be owned by the world as the async scheduling needs to own them while it is running. We could possibly store this on the schedule somehow maybe inside of a sub world on the schedule?
Other changes
Future Considerations
Allow scheduler systems to capture additional conflicts
Cancellation
In this model schedules are always run to completion. In the future, it might make sense to add support for canceling schedules, but probably requires AsyncDrop support from rust.
Combinators for States
We'll want a system for schedules and app state that is compatible and logical with state combinators.
Drawbacks
Open Questions
Prior work for structured concurrency
Beta Was this translation helpful? Give feedback.
All reactions