Skip to content

Instantly share code, notes, and snippets.

@tarunon
Created May 24, 2024 12:38
Show Gist options
  • Save tarunon/fcbe449c3ff0e3f7a51223ee7be61a6f to your computer and use it in GitHub Desktop.
Save tarunon/fcbe449c3ff0e3f7a51223ee7be61a6f to your computer and use it in GitHub Desktop.
import Foundation
// MARK: without cancel implementation
print("check without cancel implementation")
do {
print("#1 function")
func function() async -> Int {
return await withTaskCancellationHandler {
for i in 0..<5 {
try? await Task.sleep(for: .seconds(1))
print("inner function: \(i)")
}
return 1
} onCancel: {
print("function canceled")
}
}
let task = Task {
let i = await function()
print("outer function: \(i)")
print("function complete")
}
try? await Task.sleep(for: .seconds(2))
task.cancel()
try? await Task.sleep(for: .seconds(5))
}
do {
print("#2 stream")
let stream = AsyncStream<Int> {
for i in 0..<5 {
try? await Task.sleep(for: .seconds(1))
print("inner stream: \(i)")
}
return 1
} onCancel: {
print("stream canceled")
}
let task = Task {
for await i in stream {
print("outer stream: \(i)")
}
print("stream complete")
}
try? await Task.sleep(for: .seconds(2))
task.cancel()
try? await Task.sleep(for: .seconds(5))
}
// MARK: with cancel implementation
print("check with cancel implementation")
do {
print("#3 function")
func function() async -> Int {
let task = Task {
for i in 0..<5 {
try? await Task.sleep(for: .seconds(1))
print("innner function: \(i)")
}
return 1
}
return await withTaskCancellationHandler {
await task.value
} onCancel: {
task.cancel()
print("cancel function")
}
}
let task = Task {
let i = await function()
print("outer function: \(i)")
print("function complete")
}
try? await Task.sleep(for: .seconds(2))
task.cancel()
try? await Task.sleep(for: .seconds(5))
}
do {
print("#4 stream")
let stream = AsyncStream<Int> { continuation in
let task = Task {
for i in 0..<5 {
try? await Task.sleep(for: .seconds(1))
print("innner stream: \(i)")
continuation.yield(i)
}
}
continuation.onTermination = { _ in
task.cancel()
print("cancel stream")
}
}
let task = Task {
for await i in stream {
print("outer stream: \(i)")
}
print("stream complete")
}
try? await Task.sleep(for: .seconds(2))
task.cancel()
try? await Task.sleep(for: .seconds(5))
}
/* Result
check without cancel implementation
#1 function
inner function: 0
inner function: 1
function canceled
inner function: 2
inner function: 3
inner function: 4
outer function: 1
function complete
#2 stream
inner stream: 0
stream canceled
inner stream: 1
inner stream: 2
inner stream: 3
inner stream: 4
outer stream: 1
stream canceled
stream complete
check with cancel implementation
#3 function
innner function: 0
innner function: 1
cancel function
innner function: 2
innner function: 3
innner function: 4
outer function: 1
function complete
#4 stream
innner stream: 0
outer stream: 0
innner stream: 1
outer stream: 1
innner stream: 2
cancel stream
innner stream: 3
outer stream: 2
innner stream: 4
outer stream: 3
stream complete
Playground execution failed:
error: execution stopped with unexpected state.
error: Execution was interrupted.
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment