Skip to content

Instantly share code, notes, and snippets.

@gcbrueckmann
Created August 5, 2016 12:53
Show Gist options
  • Save gcbrueckmann/8af790d15b4319cfbe9bd6d515ed8768 to your computer and use it in GitHub Desktop.
Save gcbrueckmann/8af790d15b4319cfbe9bd6d515ed8768 to your computer and use it in GitHub Desktop.
A Grand Central Dispatch queue wrapper that manages a serial queue and is deadlock-safe
/// A Grand Central Dispatch queue wrapper that manages a serial queue.
/// You can dispatch blocks to the receiver asynchronously as well as synchronously
/// without running risk of a deadlock. This is in contrast to `dispatch_sync()`.
final class SerialQueue {
init() {
dispatch_queue_set_specific(queue, SerialQueue.queueIdentityKey, queueIdentity, nil)
}
private let queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL)
private let queueIdentity = UnsafeMutablePointer<Void>.alloc(1)
private static let queueIdentityKey = UnsafeMutablePointer<Void>.alloc(1)
/// Perform a block synchronously on the receiver's.
///
/// - returns: Any value returned from `block` will be returned to the caller.
///
/// The `block` argument should be marked as `@noescape`, but unfortunately the
/// block argument to `dispatch_async()` is not marked as such.
func sync<ResultType>(block: () -> ResultType) -> ResultType {
var result: ResultType! = nil
if dispatch_get_specific(SerialQueue.queueIdentityKey) == queueIdentity {
result = block()
} else {
dispatch_sync(queue) {
result = block()
}
}
return result
}
/// Perform a block asynchronously on the receiver's.
func async(block: () -> Void) {
if dispatch_get_specific(SerialQueue.queueIdentityKey) == queueIdentity {
block()
} else {
dispatch_sync(queue, block)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment