Skip to content

Instantly share code, notes, and snippets.

@zwaldowski
Forked from groue/gist:f2ecc98b8301ed63d843
Last active April 11, 2016 13:31
Show Gist options
  • Save zwaldowski/777c5b9e004122ba7930 to your computer and use it in GitHub Desktop.
Save zwaldowski/777c5b9e004122ba7930 to your computer and use it in GitHub Desktop.
A function declared as rethrows that synchronously executes a throwing block in a dispatch_queue.
import Dispatch
@_silgen_name("dispatch_sync") private func os_dispatch_sync(queue: dispatch_queue_t, @noescape _ block: dispatch_block_t)
@_silgen_name("dispatch_barrier_sync") private func os_dispatch_barrier_sync(queue: dispatch_queue_t, @noescape _ block: dispatch_block_t)
private func dispatch_sync_rethrow_wrapper<Return>(queue: dispatch_queue_t, @noescape dispatcher: (dispatch_queue_t, dispatch_block_t) -> Void, @noescape body: () throws -> Return, @noescape onError: ErrorType throws -> Void) rethrows -> Return {
var ret: Return!
var innerError: ErrorType?
os_dispatch_sync(queue) {
do {
ret = try body()
} catch {
innerError = error
}
}
if let innerError = innerError {
try onError(innerError)
}
return ret
}
// A function declared as rethrows that synchronously executes a throwing
// block in a dispatch_queue.
//
// Based on Ransak's answer to https://forums.developer.apple.com/message/19685
public func dispatch_sync<Return>(queue: dispatch_queue_t, @noescape _ body: () throws -> Return) rethrows -> Return {
return try dispatch_sync_rethrow_wrapper(queue, dispatcher: os_dispatch_sync, body: body, onError: { throw $0 })
}
public func dispatch_barrier_sync<Return>(queue: dispatch_queue_t, @noescape _ body: () throws -> Return) rethrows -> Return {
return try dispatch_sync_rethrow_wrapper(queue, dispatcher: os_dispatch_barrier_sync, body: body, onError: { throw $0 })
}
// Some error
struct SomeError: ErrorType {}
// Some queue:
let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
// try required for throwing closure:
do {
let value = try dispatch_sync(queue) { () -> Int in
throw SomeError()
}
print("returned \(value)")
} catch {
print("caught \(error)")
}
// try not required for non-throwing closure:
let value = dispatch_sync(queue) { () -> Int in
print("hello")
return 5
}
print("returned \(value)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment