Created
August 13, 2020 13:16
-
-
Save sharplet/f3a547a92135c29f2940c97c68868ab4 to your computer and use it in GitHub Desktop.
A simple generic unbuffered channel using NSCondition
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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