Last active
May 25, 2017 18:38
-
-
Save Abeansits/ca58576908a98d7e9104c33002342087 to your computer and use it in GitHub Desktop.
A thread safe callback dictionary
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
import Foundation | |
/// A thread-safe container for mapping a String key to a `CallbackBlock`. A callback-block can be invoked individually or all at once. | |
public struct CallbackDictionary<ResultType> { | |
// MARK: - Initializing | |
public init() {} | |
// MARK: - Public Interface | |
/// The block that can be called. | |
public typealias CallbackBlock = (Result<ResultType>) -> Void | |
/// Appends another block and pairs it with the `key`. If the `key` already exists it will be overwritten. | |
/// Function is thread-safe. | |
public mutating func add(callback: @escaping CallbackBlock, for key: AnyHashable) { | |
// For now let's roll with a DispatchQueue.sync sollution even though it is very inefficient. | |
// If we see a problem with this sollution or Swift get's proper synchronization support | |
// we can change this implementation. | |
// | |
// More info: https://www.cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html#an-absence-of-threading-in-swift | |
// | |
syncingQueue.sync { | |
callbackMapper[key] = callback | |
} | |
} | |
/// Will try to remove the block that is associated with the passed in `key`. | |
/// The function is thread-safe. | |
public mutating func remove(for key: AnyHashable) { | |
syncingQueue.sync { | |
let _ = callbackMapper.removeValue(forKey: key) | |
} | |
} | |
/// Calls a specific block associated to the key passed in. If no block is found it's a NOP. | |
/// The function is thread-safe. | |
public func callBlock(for key: AnyHashable, with result: Result<ResultType>) { | |
syncingQueue.sync { | |
if let block = callbackMapper[key] { | |
block(result) | |
} | |
} | |
} | |
/// Calls all the blocks stored with the passed in results. | |
/// The function is thread-safe. | |
public func callAllBlocks(with result: Result<ResultType>) { | |
syncingQueue.sync { | |
callbackMapper.values.forEach { block in | |
block(result) | |
} | |
} | |
} | |
// MARK: - Private | |
/// A serial queue is used to secure access to resources. | |
private let syncingQueue = DispatchQueue(label: "com.syncing.queue.CallbackDictionary") | |
/// The actual storage of the string keys and their blocks. It's just a regular Dictionary. | |
private var callbackMapper = [AnyHashable: CallbackBlock]() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment