Releases: swhitty/IdentifiableContinuation
0.4.0 Swift 6 Language Mode
Adds support for Swift 6 language mode when building with Xcode 16 (RC)
Uses variation of lock from swift-mutex
Swift 6 (Xcode 6 Beta 5)
Adds support for Swift 6, inheriting actor isolation through the new #isolation
keyword (SE-420).
let val: String = await withIdentifiableContinuation {
continuations[$0.id] = $0
}
Swift 5 must continuation to pass an isolated reference to the current actor.
let val: String = await withIdentifiableContinuation(isolation: self) {
continuations[$0.id] = $0
}
Swift 6
Adds support for Swift 6, inheriting actor isolation through the new #isolation
keyword (SE-420).
let val: String = await withIdentifiableContinuation {
continuations[$0.id] = $0
}
Swift 5 must continuation to pass an isolated reference to the current actor.
let val: String = await withIdentifiableContinuation(isolation: self) {
continuations[$0.id] = $0
}
Preserve calling #function
Preserves calling #function
passing it to the inner CheckedContinuation
allowing for better diagnostics.
Actor Isolation
Adds explicit actor isolation to ensure the closure is executed within the actors isolation:
let val: String = await withIdentifiableContinuation(isolation: self) {
$0.resume(returning: "bar")
}
This allows actors to synchronously start continuations and mutate their isolated state before suspension occurs. The onCancel:
handler is @Sendable
and can be called at any time after the body has completed. Manually check Task.isCancelled
before creating the continuation to prevent performing unrequired work.
let val: String = await withIdentifiableContinuation(isolation: self) {
// executed within actor isolation so can immediatley mutate actor state
continuations[$0.id] = $0
} onCancel: { id in
// @Sendable closure executed outside of actor isolation requires `await` to mutate actor state
Task { await self.cancelContinuation(with: id) }
}
Previous versions used async
closures and unstructured tasks to work with actors but SE-0420 Inheritance of Actor isolation includes the new #isolation
keyword that will allow isolation: self
to be automatically filled in by the compiler.
Async Handlers
Adds support for async
closures, making it easy to store the continuations within an actor:
let val: String? = await withIdentifiableContinuation {
await someActor.insertContinuation($0)
} onCancel: {
await someActor.cancelContinuation(for: $0)
}
The onCancel:
handler is still guaranteed to be called after the continuation body executes to completion, even if the task is already cancelled.
Initial Release
IdentifiableContinuation is a lightweight wrapper around CheckedContinuation
and UnsafeContinuation
that conforms to Identifiable
and including an easy to use cancellation handler with the id.
Usage is similar to existing continuations:
let val: String = await withIdentifiableContinuation {
$0.resume(returning: "bar")
}
The continuation includes an id
that can be attached to an asynchronous task enabling the onCancel
handler to cancel it.
let val: String? = await withIdentifiableContinuation { continuation in
foo.startTask(for: continuation.id) { result
continuation.resume(returning: result)
}
} onCancel: { id in
foo.cancelTask(for: id)
}
Initial Release
IdentifiableContinuation is a lightweight wrapper around CheckedContinuation
and UnsafeContinuation
that conforms to Identifiable
and including an easy to use cancellation handler with the id.
Usage is similar to existing continuations:
let val: String = await withIdentifiableContinuation {
$0.resume(returning: "bar")
}
The continuation includes an id
that can be attached to an asynchronous task enabling the onCancel
handler to cancel it.
let val: String? = await withIdentifiableContinuation { continuation in
foo.startTask(for: continuation.id) { result
continuation.resume(returning: result)
}
} onCancel: { id in
foo.cancelTask(for: id)
}