Skip to content

Instantly share code, notes, and snippets.

@ole
Last active December 23, 2021 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ole/2ebb2a83c65b5a243ab33eacf4d96867 to your computer and use it in GitHub Desktop.
Save ole/2ebb2a83c65b5a243ab33eacf4d96867 to your computer and use it in GitHub Desktop.
Using CheckedContinuation to communicate between concurrent tasks.
// This is the code for https://forums.swift.org/t/communicating-between-two-concurrent-tasks/54240
import _Concurrency
actor Buffer {
var elements: [Int] = []
private var isNotEmpty: CheckedContinuation<Void, Never>? = nil
deinit {
// TODO: If the continuation is not nil,
// resume it by throwing cancellation error?
}
func enqueue(_ value: Int) {
elements.append(value)
// Signal dequeue if needed.
isNotEmpty?.resume()
isNotEmpty = nil
}
func dequeue() async -> Int {
while true {
if !elements.isEmpty {
return elements.removeFirst()
} else {
// Suspend until another element is enqueued.
print("dequeue waiting")
await withCheckedContinuation { cont in
self.isNotEmpty = cont
}
}
}
}
}
Task {
let buffer = Buffer()
// Producer task
Task {
await buffer.enqueue(1)
try! await Task.sleep(nanoseconds: 400_000_000)
await buffer.enqueue(2)
await buffer.enqueue(3)
}
// Consumer task
Task {
while true {
let next = await buffer.dequeue()
print(next)
try! await Task.sleep(nanoseconds: 100_000_000)
}
}
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment