forked from mxcl/PromiseKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhang.swift
More file actions
50 lines (43 loc) · 1.55 KB
/
hang.swift
File metadata and controls
50 lines (43 loc) · 1.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import Foundation
import CoreFoundation
/**
Suspends the active thread waiting on the provided promise.
Useful when an application's main thread should not terminate before the promise is resolved
(e.g. commandline applications).
- Returns: The value of the provided promise once resolved.
- Throws: An error, should the promise be resolved with an error.
- SeeAlso: `wait()`
*/
public func hang<T>(_ promise: Promise<T>) throws -> T {
#if os(Linux)
// isMainThread is not yet implemented on Linux.
let runLoopModeRaw = RunLoopMode.defaultRunLoopMode.rawValue._bridgeToObjectiveC()
let runLoopMode: CFString = unsafeBitCast(runLoopModeRaw, to: CFString.self)
#else
guard Thread.isMainThread else {
// hang doesn't make sense on threads that aren't the main thread.
// use `.wait()` on those threads.
fatalError("Only call hang() on the main thread.")
}
let runLoopMode: CFRunLoopMode = CFRunLoopMode.defaultMode
#endif
if promise.isPending {
var context = CFRunLoopSourceContext()
let runLoop = CFRunLoopGetCurrent()
let runLoopSource = CFRunLoopSourceCreate(nil, 0, &context)
CFRunLoopAddSource(runLoop, runLoopSource, runLoopMode)
_ = promise.ensure {
CFRunLoopStop(runLoop)
}
while promise.isPending {
CFRunLoopRun()
}
CFRunLoopRemoveSource(runLoop, runLoopSource, runLoopMode)
}
switch promise.result! {
case .rejected(let error):
throw error
case .fulfilled(let value):
return value
}
}