Created
December 8, 2023 21:30
-
-
Save palmin/3d41f19e65cf0478f8a67bb01342d3f2 to your computer and use it in GitHub Desktop.
This file contains 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
// | |
// Promise.swift | |
// ShellFish | |
// | |
// Created by Anders Borum on 25/02/2019. | |
// Copyright © 2019 Anders Borum. All rights reserved. | |
// | |
import Foundation | |
// Helper functions to go from asyncronous code to syncronous by waiting on a condition triggered by | |
// the completion handler. | |
public class Promise<Result> { | |
private let condition = NSCondition() | |
private var result: Result? | |
public init() {} | |
public var completionHandler: (Result) -> Void { | |
return { result in | |
self.condition.lock() | |
self.result = result | |
self.condition.signal() | |
self.condition.unlock() | |
} | |
} | |
// blocks until completionHandler has been called and we shouldn't | |
// call this from the main thread | |
public var value: Result { | |
assert(!Thread.isMainThread) | |
condition.lock() | |
while result == nil { | |
condition.wait() | |
} | |
condition.unlock() | |
return result! | |
} | |
// blocks until completionHandler has been called and can be called from | |
// main thread but you will get deadlocks if the work we are waiting to | |
// complete will itself block the main thread | |
public var valueEvenMain: Result { | |
condition.lock() | |
while result == nil { | |
condition.wait() | |
} | |
condition.unlock() | |
return result! | |
} | |
// used to provide result when timeout passes, which can be used for | |
// timeout errors and default values | |
public func scheduleTimeout(_ timeout: TimeInterval, value: Result) { | |
DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { [weak self] in | |
self?.completionHandler(value) | |
} | |
} | |
} | |
public extension Promise where Result == Error? { | |
// throw if result is non-nil Error | |
func attempt() throws { | |
let error = value | |
if error != nil { | |
throw error! | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment