Skip to content

Instantly share code, notes, and snippets.

@miguelfermin
Created September 17, 2018 10:15
Show Gist options
  • Save miguelfermin/1628c7e227498f09c85aff668d47eb6d to your computer and use it in GitHub Desktop.
Save miguelfermin/1628c7e227498f09c85aff668d47eb6d to your computer and use it in GitHub Desktop.
Simple Swift implementation of the Future design pattern.
enum Result<T> {
case value(T)
case error(Error)
}
final class Future<T> {
private let queue: DispatchQueue
private var callbacks: [(Result<T>) -> ()] = []
private var result: Result<T>?
init(compute: (@escaping (Result<T>) -> Void) -> Void) {
let label = "com.mafsoftware.Future.\(UUID().uuidString)"
queue = DispatchQueue(label: label, attributes: .concurrent)
queue.sync {
compute(self.send)
}
}
private func send(_ value: Result<T>) {
queue.sync {
assert(result == nil)
result = value
for callback in callbacks {
callback(value)
}
callbacks = []
}
}
final func completionHandler(callback: @escaping (Result<T>) -> ()) {
queue.sync {
if let value = result {
DispatchQueue.main.async { callback(value) }
} else {
callbacks.append(callback)
}
}
}
}
// How to consume:
struct Car { let make: String, model: String }
// a func that returns a Future "Car"
func fetchCat() -> Future<Car> {
let future = Future<Car> { result in
Time.sleep(for: 1) {result(.value(Car(make: "Honda", model: "Civic")))}
}
return future
}
let carFuture = fetchCat()
carFuture.completionHandler { result in
switch result {
case .value(let value): print("value0: \(value)")
case .error(let error): print("error: \(error)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment