Created
June 14, 2021 12:01
-
-
Save shaps80/1f7c218451d53afc2f812918bca3024a to your computer and use it in GitHub Desktop.
Atomic RangeReplaceableCollection Storage in Swift
This file contains 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 | |
public final class Store<Element>: RangeReplaceableCollection { | |
public typealias Index = Int | |
public typealias SubSequence = Store<Element> | |
public var startIndex: Index { queue.sync { storage.startIndex } } | |
public var endIndex: Index { queue.sync { storage.endIndex } } | |
public func index(after i: Index) -> Index { queue.sync { storage.index(after: i) } } | |
private lazy var queue: DispatchQueue = { | |
DispatchQueue(label: "store-\(String(describing: Element.self))", qos: .background, attributes: .concurrent) | |
}() | |
fileprivate private(set) var storage: [Element] | |
public var isEmpty: Bool { | |
queue.sync { storage.isEmpty } | |
} | |
public var count: Int { | |
queue.sync { storage.count } | |
} | |
public var indices: Range<Index> { | |
queue.sync { storage.indices } | |
} | |
public init() { | |
storage = [] | |
} | |
public init<S>(_ elements: S) where S: Sequence, Element == S.Element { | |
storage = Array<S.Element>(elements) | |
} | |
public subscript(bounds: Range<Index>) -> SubSequence { | |
queue.sync { .init(storage[bounds]) } | |
} | |
public subscript(bounds: Index) -> Element { | |
get { | |
queue.sync { storage[bounds] } | |
} | |
set { | |
queue.async(flags: .barrier) { self.storage[bounds] = newValue } | |
} | |
} | |
public func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C) where C: Collection, Element == C.Element { | |
queue.async(flags: .barrier) { | |
self.storage.replaceSubrange(subrange, with: newElements) | |
} | |
} | |
} | |
extension Store: Codable where Element: Codable { } | |
extension Store: Equatable where Element: Equatable { | |
public static func == (lhs: Store<Element>, rhs: Store<Element>) -> Bool { | |
lhs.storage == rhs.storage | |
} | |
} | |
extension Store: Hashable where Element: Hashable { | |
public func hash(into hasher: inout Hasher) { | |
hasher.combine(storage) | |
} | |
} | |
extension Store: CustomReflectable { | |
public var customMirror: Mirror { | |
Mirror(reflecting: storage) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment