ScopedCloseable
Base for coordinators that launch coroutines into an owned child scope and implement AutoCloseable.
Ownership model
The constructor creates a SupervisorJob that is a child of the parent scope's job, so:
A crashing child coroutine does not propagate to the caller's scope (supervisor boundary).
Parent-scope cancellation still propagates down — ownJob is a structural child.
Every
scope.launchinside this class is automatically a child of ownJob; no manual job list is needed. Job-list drift (a launch that escapes close) is structurally impossible.
Close contract
close is idempotent — safe to call multiple times. On the first call it invokes onClose (subclass hook for cleanup work), then cancels ownJob, which cancels all child coroutines. Subsequent calls are no-ops.
Subclasses must launch all background coroutines into scope (not into the caller's scope). Launching into the caller's scope bypasses the ownership invariant.
Parameters
the caller's CoroutineScope. ownJob becomes a child of its Job.