Skip to content

Instantly share code, notes, and snippets.

@sharplet
Created August 13, 2020 13:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sharplet/f3a547a92135c29f2940c97c68868ab4 to your computer and use it in GitHub Desktop.
Save sharplet/f3a547a92135c29f2940c97c68868ab4 to your computer and use it in GitHub Desktop.
A simple generic unbuffered channel using NSCondition
import Foundation
class Channel<Message> {
private enum State {
case empty
case readyToReceive
case full(Message)
}
private let condition: NSCondition
private var message: Message!
private var state: State
init() {
self.condition = NSCondition()
self.state = .empty
}
func send(_ message: Message) {
condition.lock()
defer { condition.unlock() }
loop: do {
switch state {
case .empty, .full:
condition.wait()
continue loop
case .readyToReceive:
state = .full(message)
condition.signal()
}
}
}
func receive() -> Message {
condition.lock()
defer { condition.unlock() }
loop: do {
switch state {
case .empty:
state = .readyToReceive
condition.signal()
condition.wait()
continue loop
case .readyToReceive:
condition.wait()
continue loop
case let .full(message):
state = .empty
condition.signal()
return message
}
}
}
}
let channel = Channel<String>()
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
channel.send("Hello, world!")
}
print(Date())
let message = channel.receive()
print(message)
print(Date())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment