Skip to content

Instantly share code, notes, and snippets.

@shaps80
Created June 14, 2021 12:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shaps80/1f7c218451d53afc2f812918bca3024a to your computer and use it in GitHub Desktop.
Save shaps80/1f7c218451d53afc2f812918bca3024a to your computer and use it in GitHub Desktop.
Atomic RangeReplaceableCollection Storage in Swift
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