Skip to content

Commit f4514dd

Browse files
More implementation details for atomic ordering constraints
1 parent c9ab553 commit f4514dd

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

rfcs/45-stageless.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,7 @@ In order to understand exactly what this means, we need to understand atomic ord
230230
At least, as far as "directly after" is a meaningful concept in a parallel, nonlinear ordering.
231231
Like the atom, they are indivisible: nothing can get between them!
232232

233-
To be fully precise, if we have system `A` that runs "atomically before" system `B` (`.add_system(a.atomically_before(b))`):
234-
235-
- `A` is strictly before `B`
236-
- the "write" data locks of system `A` are relaxed to "read" data locks upon system `A`'s completion
237-
- "read" data locks of system `A` will not be released until system `B` (and all other atomic dependents) has completed
238-
- the data locks from system `A` are ignored for the purposes of checking if system `B` can run
239-
- after all, they're not actualy locked, merely reserved
240-
- competing read-locks caused by other systems will still need to complete before a data store can be mutated; the effect is to "ignore the locks of `A`", not "skip the check completely"
233+
To be more precise, if a system `A` is `atomically_before` system `B`, nothing (other than system `B`) can mutate the data that system `A` could access.
241234

242235
In addition to their use in run criteria, atomic ordering constraints are extremely useful for forcing tight interlocking behavior between systems.
243236
They allow us to ensure that the state read from and written to the earlier system cannot be invalidated.
@@ -450,6 +443,21 @@ struct SystemConfig {
450443
}
451444
```
452445

446+
### Atomic ordering constraints
447+
448+
To be fully precise, if we have system `A` that runs "atomically before" system `B` (`.add_system(a.atomically_before(b))`):
449+
450+
- `A` is strictly before `B`
451+
- the "write" data locks of system `A` are relaxed to "read" data locks upon system `A`'s completion
452+
- "read" data locks of system `A` will not be released until system `B` (and all other atomic dependents) have completed
453+
- the data locks from system `A` are ignored for the purposes of checking if system `B` can run
454+
- after all, they're not actualy locked, merely reserved
455+
- competing read-locks caused by other systems will still need to complete before a data store can be mutated; the effect is to "ignore the locks of `A`", not "skip the check completely"
456+
- if and only if `A` has multiple atomic dependents, they cannot mutate the data read by `A`, as that would invalidate the state created by `A` that other dependents may be relying on
457+
458+
In addition, atomic ordering constraints introduce a new form of schedule unsatisfiability.
459+
If a system must run between `A` and `B`, but can mutate data that `A` has access to, the schedule is unsatisfiable.
460+
453461
### Flushed ordering constraints
454462

455463
Being able to assert that commands are processed (or state is flushed) between two systems is a critical requirement for being able to specify logically-meaningful ordering of systems without a global view of the schedule.
@@ -529,6 +537,8 @@ There are two reasons why this doesn't work:
529537
In practice, almost all run criteria are extremely simple, and fast to check.
530538
Verifying that the cache is still valid will require access to the data anyways, and involve more overhead than simple computations on one or two resources.
531539

540+
In addition, adding multiple atomic ordering constraints originating from a single system is extremely prone to dead-locks; we should not hand users this foot-gun.
541+
532542
### Why do we want to store multiple schedules in the `App`?
533543

534544
We could store these in a resource in the `World`.

0 commit comments

Comments
 (0)