Created
August 5, 2016 12:53
-
-
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
This file contains hidden or 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
/// 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