import Foundation public class ConcurrentDictionary: Collection { private var inner: [V : T] private var lock: NSLock = .init() public var keys: Dictionary.Keys { self.locked { inner.keys } } public var values: Dictionary.Values { self.locked { self.inner.values } } public var startIndex: Dictionary.Index { self.locked { self.inner.startIndex } } public var endIndex: Dictionary.Index { self.locked { self.inner.endIndex } } public init(inner: [V:T]) { self.inner = inner } public convenience init() { self.init(inner: [:]) } public func index(after i: Dictionary.Index) -> Dictionary.Index { self.locked { self.inner.index(after: i) } } public subscript(key: V) -> T? { set(newValue) { self.locked { self.inner[key] = newValue } } get { self.locked { self.inner[key] } } } public subscript(index: Dictionary.Index) -> Dictionary.Element { self.locked { self.inner[index] } } public func take() -> Dictionary { self.locked { let current = self.inner self.inner = [:] return current } } public func removeAll(keepingCapacity keep: Bool = false) { self.locked { self.inner.removeAll(keepingCapacity: keep) } } @discardableResult public func remove(key: V) -> T? { self.locked { self.inner.removeValue(forKey: key) } } public func with(_ perform: (inout [V : T]) -> Void) { self.locked { perform(&self.inner) } } fileprivate func locked(_ perform: () -> X) -> X { self.lock.lock() defer { self.lock.unlock() } let value = perform() return value } }