onCleanup abstract method
void
onCleanup(
- void cleanup()
Registers a synchronous cleanup callback to be executed upon turn cancellation or deactivation.
Multi-Registration & Locality of Reference (RAII)
You can call onCleanup multiple times within a single effect turn. Registering cleanups immediately adjacent to resource acquisition guarantees exception safety and modular decomposition:
Effect.scoped([room.bloom], (scope) {
// Resource 1: acquired and immediately guarded
final timer = Timer.periodic(const Duration(seconds: 1), (_) => ping());
scope.onCleanup(timer.cancel);
// Resource 2: acquired and immediately guarded
final sub = eventStream.listen(onEvent);
scope.onCleanup(sub.cancel);
});
Architectural Rationales
- Exception Safety during Setup: If an exception is thrown while acquiring a subsequent resource, previously registered cleanups remain intact and execute reliably.
- Modular Composition: Enables passing EffectScope into independent helper functions allowing each sub-routine to safely register its own cleanup without overwriting others.
- Clean Conditional Branching: Resources acquired inside
ifblocks can register their respective teardowns directly in-place without nullable tracking variables.
Execution Timing
Cleanups are NOT executed immediately when the action function returns. They remain dormant and active while the current turn is valid, and are executed:
-
Right before the next execution turn begins (upon upstream mutation).
-
When the effect is deactivated or unmounted (upon scope exit / disposal).
-
cleanup: The synchronous callback to execute when this turn is cancelled or deactivated.
Ensures:
- If this scope is already cancelled, executes
cleanupimmediately. - Otherwise, chains
cleanupinto the pending teardown pipeline.
Implementation
void onCleanup(void Function() cleanup);