Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created February 16, 2018 12:36
Show Gist options
  • Select an option

  • Save chriseidhof/d70244716ce0a40661b9e71269791b03 to your computer and use it in GitHub Desktop.

Select an option

Save chriseidhof/d70244716ce0a40661b9e71269791b03 to your computer and use it in GitHub Desktop.
goroutines.swift
import Foundation
protocol Channel: IteratorProtocol {
func send(_ value: Element?)
}
/// A blocking channel for sending values.
///
/// `send` and `receive` must run in separate separate execution contexts, otherwise you get a deadlock.
final class BlockingChannel<A>: Channel {
let producer = DispatchSemaphore(value: 0)
let consumer = DispatchSemaphore(value: 0)
private var value: A?
var done: Bool = false
func send(_ value: A?) {
producer.wait()
self.value = value
if value == nil { done = true }
consumer.signal()
}
func next() -> A? {
guard !done else { return nil }
producer.signal()
consumer.wait()
return value
}
}
final class BufferedChannel<A>: Channel {
let valueQueue = DispatchQueue(label: "sync value")
let consumer = DispatchSemaphore(value: 0)
private var values: [A] = []
var done: Bool = false
func send(_ value: A?) {
if let v = value {
self.valueQueue.sync {
self.values.append(v)
}
} else {
done = true
}
consumer.signal()
}
func next() -> A? {
guard !done else {
return values.isEmpty ? nil : values.removeFirst()
}
consumer.wait()
var result: A? = nil
valueQueue.sync {
result = values.removeFirst()
}
return result
}
}
func go(_ f: @escaping () -> ()) -> () {
DispatchQueue.global().async {
f()
}
}
infix operator <-
func <-<C, A>(lhs: C, rhs: A?) where C: Channel, C.Element == A {
lhs.send(rhs)
}
func test() {
let channel = BufferedChannel<Int>()
go {
channel <- 1
channel <- 2
channel <- nil // done
}
sleep(1)
while let value = channel.next() {
print(value)
}
}
test()
@13hoop
Copy link
Copy Markdown

13hoop commented Feb 18, 2018

nice
thanks for sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment