ScopedCloseable

abstract class ScopedCloseable(parentScope: CoroutineScope) : AutoCloseable

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.launch inside 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 and thread-safe — safe to call multiple times, from any thread, concurrently. Exactly one call wins the guard; it invokes onClose (subclass hook for cleanup work), then cancels ownJob, which cancels all child coroutines. Every other call is a no-op.

The guard is a once barrier, not a completion barrier: a losing concurrent caller returns immediately and may do so while the winner is still inside onClose. Returning from close therefore means "cleanup has been initiated exactly once", never "everything has stopped" — which is already true of the winning caller too, since Job.cancel is asynchronous and child coroutines may still be unwinding after it returns. Callers that need quiescence must join: subclasses can expose ownJob for that. Blocking a loser until the winner finishes was considered and rejected — close is a non-suspend function on every target (including single-threaded wasmJs), so a completion barrier would have to block a thread, and this repo's own onClose bodies close other ScopedCloseables from inside the hook, which is exactly the shape that turns a blocking close into a lock-ordering deadlock.

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

parentScope

the caller's CoroutineScope. ownJob becomes a child of its Job.

Inheritors

Constructors

Link copied to clipboard
constructor(parentScope: CoroutineScope)

Functions

Link copied to clipboard
override fun close()

Cancels all background coroutines owned by this instance. Idempotent and thread-safe — safe to call multiple times, from any thread, concurrently.