123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- import Foundation
- import UIKit
- public class ThreadSafeArray<Element> {
- private var array = [Element]()
- private let queue = DispatchQueue(label: "com.nextcloud.ThreadSafeArray", attributes: .concurrent)
- public init() { }
- public convenience init(_ array: [Element]) {
- self.init()
- self.array = array
- }
- }
- public extension ThreadSafeArray {
-
- var first: Element? {
- var result: Element?
- queue.sync { result = self.array.first }
- return result
- }
-
- var last: Element? {
- var result: Element?
- queue.sync { result = self.array.last }
- return result
- }
-
- var count: Int {
- var result = 0
- queue.sync { result = self.array.count }
- return result
- }
-
- var isEmpty: Bool {
- var result = false
- queue.sync { result = self.array.isEmpty }
- return result
- }
-
- var description: String {
- var result = ""
- queue.sync { result = self.array.description }
- return result
- }
- }
- public extension ThreadSafeArray {
-
-
-
-
- func first(where predicate: (Element) -> Bool) -> Element? {
- var result: Element?
- queue.sync { result = self.array.first(where: predicate) }
- return result
- }
-
-
-
-
- func last(where predicate: (Element) -> Bool) -> Element? {
- var result: Element?
- queue.sync { result = self.array.last(where: predicate) }
- return result
- }
-
-
-
-
- func filter(_ isIncluded: @escaping (Element) -> Bool) -> ThreadSafeArray {
- var result: ThreadSafeArray?
- queue.sync { result = ThreadSafeArray(self.array.filter(isIncluded)) }
- return result!
- }
-
-
-
-
- func index(where predicate: (Element) -> Bool) -> Int? {
- var result: Int?
- queue.sync { result = self.array.firstIndex(where: predicate) }
- return result
- }
-
-
-
-
- func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> ThreadSafeArray {
- var result: ThreadSafeArray?
- queue.sync { result = ThreadSafeArray(self.array.sorted(by: areInIncreasingOrder)) }
- return result!
- }
-
-
-
-
- func map<ElementOfResult>(_ transform: @escaping (Element) -> ElementOfResult) -> [ElementOfResult] {
- var result = [ElementOfResult]()
- queue.sync { result = self.array.map(transform) }
- return result
- }
-
-
-
-
- func compactMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] {
- var result = [ElementOfResult]()
- queue.sync { result = self.array.compactMap(transform) }
- return result
- }
-
-
-
-
-
-
- func reduce<ElementOfResult>(_ initialResult: ElementOfResult, _ nextPartialResult: @escaping (ElementOfResult, Element) -> ElementOfResult) -> ElementOfResult {
- var result: ElementOfResult?
- queue.sync { result = self.array.reduce(initialResult, nextPartialResult) }
- return result ?? initialResult
- }
-
-
-
-
-
-
- func reduce<ElementOfResult>(into initialResult: ElementOfResult, _ updateAccumulatingResult: @escaping (inout ElementOfResult, Element) -> Void) -> ElementOfResult {
- var result: ElementOfResult?
- queue.sync { result = self.array.reduce(into: initialResult, updateAccumulatingResult) }
- return result ?? initialResult
- }
-
-
-
- func forEach(_ body: (Element) -> Void) {
- queue.sync { self.array.forEach(body) }
- }
-
-
-
-
- func contains(where predicate: (Element) -> Bool) -> Bool {
- var result = false
- queue.sync { result = self.array.contains(where: predicate) }
- return result
- }
-
-
-
-
- func allSatisfy(_ predicate: (Element) -> Bool) -> Bool {
- var result = false
- queue.sync { result = self.array.allSatisfy(predicate) }
- return result
- }
-
-
-
- func getArray() -> [Element]? {
- var results: [Element]?
- queue.sync { results = self.array }
- return results
- }
- }
- public extension ThreadSafeArray {
-
-
-
- func append(_ element: Element) {
- queue.async(flags: .barrier) {
- self.array.append(element)
- }
- }
-
-
-
- func append(_ elements: [Element]) {
- queue.async(flags: .barrier) {
- self.array += elements
- }
- }
-
-
-
-
-
- func insert(_ element: Element, at index: Int) {
- queue.async(flags: .barrier) {
- self.array.insert(element, at: index)
- }
- }
-
-
-
-
-
- func remove(at index: Int, completion: ((Element) -> Void)? = nil) {
- queue.async(flags: .barrier) {
- let element = self.array.remove(at: index)
- DispatchQueue.main.async { completion?(element) }
- }
- }
-
-
-
-
-
- func remove(where predicate: @escaping (Element) -> Bool, completion: (([Element]) -> Void)? = nil) {
- queue.async(flags: .barrier) {
- var elements = [Element]()
- while let index = self.array.firstIndex(where: predicate) {
- elements.append(self.array.remove(at: index))
- }
- DispatchQueue.main.async { completion?(elements) }
- }
- }
-
-
-
- func removeAll(completion: (([Element]) -> Void)? = nil) {
- queue.async(flags: .barrier) {
- let elements = self.array
- self.array.removeAll()
- DispatchQueue.main.async { completion?(elements) }
- }
- }
- }
- public extension ThreadSafeArray {
-
-
-
-
- subscript(index: Int) -> Element? {
- get {
- var result: Element?
- queue.sync {
- guard self.array.startIndex..<self.array.endIndex ~= index else { return }
- result = self.array[index]
- }
- return result
- }
- set {
- guard let newValue = newValue else { return }
- queue.async(flags: .barrier) {
- self.array[index] = newValue
- }
- }
- }
- }
- public extension ThreadSafeArray where Element: Equatable {
-
-
-
-
- func contains(_ element: Element) -> Bool {
- var result = false
- queue.sync { result = self.array.contains(element) }
- return result
- }
- }
- public extension ThreadSafeArray {
-
-
-
-
-
- static func += (left: inout ThreadSafeArray, right: Element) {
- left.append(right)
- }
-
-
-
-
-
- static func += (left: inout ThreadSafeArray, right: [Element]) {
- left.append(right)
- }
- }
|