Skip to content

Instantly share code, notes, and snippets.

@basememara
Last active November 2, 2025 14:32
Show Gist options
  • Select an option

  • Save basememara/afaae5310a6a6b97bdcdbe4c2fdcd0c6 to your computer and use it in GitHub Desktop.

Select an option

Save basememara/afaae5310a6a6b97bdcdbe4c2fdcd0c6 to your computer and use it in GitHub Desktop.

Revisions

  1. basememara revised this gist Dec 5, 2018. 1 changed file with 122 additions and 75 deletions.
    197 changes: 122 additions & 75 deletions SynchronizedArray.swift
    Original file line number Diff line number Diff line change
    @@ -3,41 +3,49 @@ import PlaygroundSupport

    /// A thread-safe array.
    public class SynchronizedArray<Element> {
    fileprivate let queue = DispatchQueue(label: "io.zamzam.ZamzamKit.SynchronizedArray", attributes: .concurrent)
    fileprivate var array = [Element]()
    private let queue = DispatchQueue(label: "io.zamzam.ZamzamKit.SynchronizedArray", attributes: .concurrent)
    private var array = [Element]()

    public init() { }

    public convenience init(_ array: [Element]) {
    self.init()
    self.array = array
    }
    }

    // MARK: - Properties
    public extension SynchronizedArray {

    public extension SynchronizedArray {

    /// The first element of the collection.
    var first: Element? {
    var result: Element?
    queue.sync { result = self.array.first }
    return result
    }

    /// The last element of the collection.
    var last: Element? {
    var result: Element?
    queue.sync { result = self.array.last }
    return result
    }

    /// The number of elements in the array.
    var count: Int {
    var result = 0
    queue.sync { result = self.array.count }
    return result
    }

    /// A Boolean value indicating whether the collection is empty.
    var isEmpty: Bool {
    var result = false
    queue.sync { result = self.array.isEmpty }
    return result
    }

    /// A textual representation of the array and its elements.
    var description: String {
    var result = ""
    @@ -47,25 +55,37 @@ public extension SynchronizedArray {
    }

    // MARK: - Immutable

    public extension SynchronizedArray {
    /// Returns the first element of the sequence that satisfies the given predicate or nil if no such element is found.

    /// Returns the first element of the sequence that satisfies the given predicate.
    ///
    /// - Parameter predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element is a match.
    /// - Returns: The first match or nil if there was no match.
    /// - Returns: The first element of the sequence that satisfies predicate, or nil if there is no element that satisfies predicate.
    func first(where predicate: (Element) -> Bool) -> Element? {
    var result: Element?
    queue.sync { result = self.array.first(where: predicate) }
    return result
    }

    /// Returns the last element of the sequence that satisfies the given predicate.
    ///
    /// - Parameter predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element is a match.
    /// - Returns: The last element of the sequence that satisfies predicate, or nil if there is no element that satisfies predicate.
    func last(where predicate: (Element) -> Bool) -> Element? {
    var result: Element?
    queue.sync { result = self.array.last(where: predicate) }
    return result
    }

    /// Returns an array containing, in order, the elements of the sequence that satisfy the given predicate.
    ///
    /// - Parameter isIncluded: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element should be included in the returned array.
    /// - Returns: An array of the elements that includeElement allowed.
    func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
    var result = [Element]()
    queue.sync { result = self.array.filter(isIncluded) }
    return result
    func filter(_ isIncluded: @escaping (Element) -> Bool) -> SynchronizedArray {
    var result: SynchronizedArray?
    queue.sync { result = SynchronizedArray(self.array.filter(isIncluded)) }
    return result!
    }

    /// Returns the first index in which an element of the collection satisfies the given predicate.
    @@ -82,22 +102,56 @@ public extension SynchronizedArray {
    ///
    /// - Parameter areInIncreasingOrder: A predicate that returns true if its first argument should be ordered before its second argument; otherwise, false.
    /// - Returns: A sorted array of the collection’s elements.
    func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element] {
    var result = [Element]()
    queue.sync { result = self.array.sorted(by: areInIncreasingOrder) }
    func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> SynchronizedArray {
    var result: SynchronizedArray?
    queue.sync { result = SynchronizedArray(self.array.sorted(by: areInIncreasingOrder)) }
    return result!
    }

    /// Returns an array containing the results of mapping the given closure over the sequence’s elements.
    ///
    /// - Parameter transform: A closure that accepts an element of this sequence as its argument and returns an optional value.
    /// - Returns: An array of the non-nil results of calling transform with each element of the sequence.
    func map<ElementOfResult>(_ transform: @escaping (Element) -> ElementOfResult) -> [ElementOfResult] {
    var result = [ElementOfResult]()
    queue.sync { result = self.array.map(transform) }
    return result
    }

    /// Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
    ///
    /// - Parameter transform: A closure that accepts an element of this sequence as its argument and returns an optional value.
    /// - Returns: An array of the non-nil results of calling transform with each element of the sequence.
    func flatMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] {
    func compactMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] {
    var result = [ElementOfResult]()
    queue.sync { result = self.array.flatMap(transform) }
    queue.sync { result = self.array.compactMap(transform) }
    return result
    }


    /// Returns the result of combining the elements of the sequence using the given closure.
    ///
    /// - Parameters:
    /// - initialResult: The value to use as the initial accumulating value. initialResult is passed to nextPartialResult the first time the closure is executed.
    /// - nextPartialResult: A closure that combines an accumulating value and an element of the sequence into a new accumulating value, to be used in the next call of the nextPartialResult closure or returned to the caller.
    /// - Returns: The final accumulated value. If the sequence has no elements, the result is initialResult.
    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
    }

    /// Returns the result of combining the elements of the sequence using the given closure.
    ///
    /// - Parameters:
    /// - initialResult: The value to use as the initial accumulating value.
    /// - updateAccumulatingResult: A closure that updates the accumulating value with an element of the sequence.
    /// - Returns: The final accumulated value. If the sequence has no elements, the result is initialResult.
    func reduce<ElementOfResult>(into initialResult: ElementOfResult, _ updateAccumulatingResult: @escaping (inout ElementOfResult, Element) -> ()) -> ElementOfResult {
    var result: ElementOfResult?
    queue.sync { result = self.array.reduce(into: initialResult, updateAccumulatingResult) }
    return result ?? initialResult
    }

    /// Calls the given closure on each element in the sequence in the same order as a for-in loop.
    ///
    /// - Parameter body: A closure that takes an element of the sequence as a parameter.
    @@ -114,40 +168,51 @@ public extension SynchronizedArray {
    queue.sync { result = self.array.contains(where: predicate) }
    return result
    }

    /// Returns a Boolean value indicating whether every element of a sequence satisfies a given predicate.
    ///
    /// - Parameter predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value that indicates whether the passed element satisfies a condition.
    /// - Returns: true if the sequence contains only elements that satisfy predicate; otherwise, false.
    func allSatisfy(_ predicate: (Element) -> Bool) -> Bool {
    var result = false
    queue.sync { result = self.array.allSatisfy(predicate) }
    return result
    }
    }

    // MARK: - Mutable
    public extension SynchronizedArray {

    public extension SynchronizedArray {

    /// Adds a new element at the end of the array.
    ///
    /// - Parameter element: The element to append to the array.
    func append( _ element: Element) {
    func append(_ element: Element) {
    queue.async(flags: .barrier) {
    self.array.append(element)
    }
    }

    /// Adds a new element at the end of the array.
    /// Adds new elements at the end of the array.
    ///
    /// - Parameter element: The element to append to the array.
    func append( _ elements: [Element]) {
    /// - Parameter element: The elements to append to the array.
    func append(_ elements: [Element]) {
    queue.async(flags: .barrier) {
    self.array += elements
    }
    }

    /// Inserts a new element at the specified position.
    ///
    /// - Parameters:
    /// - element: The new element to insert into the array.
    /// - index: The position at which to insert the new element.
    func insert( _ element: Element, at index: Int) {
    func insert(_ element: Element, at index: Int) {
    queue.async(flags: .barrier) {
    self.array.insert(element, at: index)
    }
    }

    /// Removes and returns the element at the specified position.
    ///
    /// - Parameters:
    @@ -156,50 +221,45 @@ public extension SynchronizedArray {
    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)
    }
    DispatchQueue.main.async { completion?(element) }
    }
    }

    /// Removes and returns the element at the specified position.
    /// Removes and returns the elements that meet the criteria.
    ///
    /// - Parameters:
    /// - predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element is a match.
    /// - completion: The handler with the removed element.
    func remove(where predicate: @escaping (Element) -> Bool, completion: ((Element) -> Void)? = nil) {
    /// - completion: The handler with the removed elements.
    func remove(where predicate: @escaping (Element) -> Bool, completion: (([Element]) -> Void)? = nil) {
    queue.async(flags: .barrier) {
    guard let index = self.array.index(where: predicate) else { return }
    let element = self.array.remove(at: index)
    var elements = [Element]()

    DispatchQueue.main.async {
    completion?(element)
    while let index = self.array.index(where: predicate) {
    elements.append(self.array.remove(at: index))
    }

    DispatchQueue.main.async { completion?(elements) }
    }
    }

    /// Removes all elements from the array.
    ///
    /// - Parameter completion: The handler with the removed elements.
    func removeAll(completion: (([Element]) -> Void)? = nil) {
    queue.async(flags: .barrier) {
    let elements = self.array
    self.array.removeAll()

    DispatchQueue.main.async {
    completion?(elements)
    }
    DispatchQueue.main.async { completion?(elements) }
    }
    }
    }

    public extension SynchronizedArray {

    /// Accesses the element at the specified position if it exists.
    ///
    /// - Parameter index: The position of the element to access.
    /// - Returns: optional element if it exists.
    ///
    /// - Parameter index: The position of the element to access.
    /// - Returns: optional element if it exists.
    subscript(index: Int) -> Element? {
    get {
    var result: Element?
    @@ -221,10 +281,10 @@ public extension SynchronizedArray {
    }
    }


    // MARK: - Equatable
    public extension SynchronizedArray where Element: Equatable {

    public extension SynchronizedArray where Element: Equatable {

    /// Returns a Boolean value indicating whether the sequence contains the given element.
    ///
    /// - Parameter element: The element to find in the sequence.
    @@ -237,41 +297,28 @@ public extension SynchronizedArray where Element: Equatable {
    }

    // MARK: - Infix operators
    public extension SynchronizedArray {

    public extension SynchronizedArray {

    /// Adds a new element at the end of the array.
    ///
    /// - Parameters:
    /// - left: The collection to append to.
    /// - right: The element to append to the array.
    static func +=(left: inout SynchronizedArray, right: Element) {
    left.append(right)
    }


    /// Adds new elements at the end of the array.
    ///
    /// - Parameters:
    /// - left: The collection to append to.
    /// - right: The elements to append to the array.
    static func +=(left: inout SynchronizedArray, right: [Element]) {
    left.append(right)
    }
    }

    // Thread-unsafe array
    do {
    var array = [Int]()
    var iterations = 1000
    let start = Date().timeIntervalSince1970

    DispatchQueue.concurrentPerform(iterations: iterations) { index in
    let last = array.last ?? 0
    array.append(last + 1)

    DispatchQueue.global().sync {
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Unsafe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count
    )
    print(message)
    }
    }
    }

    // Thread-safe array
    do {
    var array = SynchronizedArray<Int>()
  2. basememara revised this gist Sep 24, 2017. 1 changed file with 10 additions and 7 deletions.
    17 changes: 10 additions & 7 deletions SynchronizedArray.swift
    Original file line number Diff line number Diff line change
    @@ -281,14 +281,17 @@ do {
    DispatchQueue.concurrentPerform(iterations: iterations) { index in
    let last = array.last ?? 0
    array.append(last + 1)
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Safe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count)
    print(message)
    DispatchQueue.global().sync {
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Safe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count)
    print(message)
    }
    }
    }

  3. basememara revised this gist Sep 24, 2017. 1 changed file with 11 additions and 7 deletions.
    18 changes: 11 additions & 7 deletions SynchronizedArray.swift
    Original file line number Diff line number Diff line change
    @@ -257,14 +257,18 @@ do {
    DispatchQueue.concurrentPerform(iterations: iterations) { index in
    let last = array.last ?? 0
    array.append(last + 1)
    iterations -= 1

    DispatchQueue.global().sync {
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Unsafe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count)
    print(message)
    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Unsafe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count
    )
    print(message)
    }
    }
    }

  4. basememara revised this gist Mar 3, 2017. 1 changed file with 52 additions and 0 deletions.
    52 changes: 52 additions & 0 deletions SynchronizedArray.swift
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,7 @@ public class SynchronizedArray<Element> {
    fileprivate var array = [Element]()
    }

    // MARK: - Properties
    public extension SynchronizedArray {

    /// The first element of the collection.
    @@ -45,6 +46,7 @@ public extension SynchronizedArray {
    }
    }

    // MARK: - Immutable
    public extension SynchronizedArray {
    /// Returns the first element of the sequence that satisfies the given predicate or nil if no such element is found.
    ///
    @@ -66,6 +68,16 @@ public extension SynchronizedArray {
    return result
    }

    /// Returns the first index in which an element of the collection satisfies the given predicate.
    ///
    /// - Parameter predicate: A closure that takes an element as its argument and returns a Boolean value that indicates whether the passed element represents a match.
    /// - Returns: The index of the first element for which predicate returns true. If no elements in the collection satisfy the given predicate, returns nil.
    func index(where predicate: (Element) -> Bool) -> Int? {
    var result: Int?
    queue.sync { result = self.array.index(where: predicate) }
    return result
    }

    /// Returns the elements of the collection, sorted using the given predicate as the comparison between elements.
    ///
    /// - Parameter areInIncreasingOrder: A predicate that returns true if its first argument should be ordered before its second argument; otherwise, false.
    @@ -104,6 +116,7 @@ public extension SynchronizedArray {
    }
    }

    // MARK: - Mutable
    public extension SynchronizedArray {

    /// Adds a new element at the end of the array.
    @@ -115,6 +128,15 @@ public extension SynchronizedArray {
    }
    }

    /// Adds a new element at the end of the array.
    ///
    /// - Parameter element: The element to append to the array.
    func append( _ elements: [Element]) {
    queue.async(flags: .barrier) {
    self.array += elements
    }
    }

    /// Inserts a new element at the specified position.
    ///
    /// - Parameters:
    @@ -140,6 +162,22 @@ public extension SynchronizedArray {
    }
    }
    }

    /// Removes and returns the element at the specified position.
    ///
    /// - Parameters:
    /// - predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element is a match.
    /// - completion: The handler with the removed element.
    func remove(where predicate: @escaping (Element) -> Bool, completion: ((Element) -> Void)? = nil) {
    queue.async(flags: .barrier) {
    guard let index = self.array.index(where: predicate) else { return }
    let element = self.array.remove(at: index)

    DispatchQueue.main.async {
    completion?(element)
    }
    }
    }

    /// Removes all elements from the array.
    ///
    @@ -183,6 +221,8 @@ public extension SynchronizedArray {
    }
    }


    // MARK: - Equatable
    public extension SynchronizedArray where Element: Equatable {

    /// Returns a Boolean value indicating whether the sequence contains the given element.
    @@ -195,6 +235,18 @@ public extension SynchronizedArray where Element: Equatable {
    return result
    }
    }

    // MARK: - Infix operators
    public extension SynchronizedArray {

    static func +=(left: inout SynchronizedArray, right: Element) {
    left.append(right)
    }

    static func +=(left: inout SynchronizedArray, right: [Element]) {
    left.append(right)
    }
    }

    // Thread-unsafe array
    do {
  5. basememara created this gist Mar 1, 2017.
    239 changes: 239 additions & 0 deletions SynchronizedArray.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,239 @@
    import Foundation
    import PlaygroundSupport

    /// A thread-safe array.
    public class SynchronizedArray<Element> {
    fileprivate let queue = DispatchQueue(label: "io.zamzam.ZamzamKit.SynchronizedArray", attributes: .concurrent)
    fileprivate var array = [Element]()
    }

    public extension SynchronizedArray {

    /// The first element of the collection.
    var first: Element? {
    var result: Element?
    queue.sync { result = self.array.first }
    return result
    }

    /// The last element of the collection.
    var last: Element? {
    var result: Element?
    queue.sync { result = self.array.last }
    return result
    }

    /// The number of elements in the array.
    var count: Int {
    var result = 0
    queue.sync { result = self.array.count }
    return result
    }

    /// A Boolean value indicating whether the collection is empty.
    var isEmpty: Bool {
    var result = false
    queue.sync { result = self.array.isEmpty }
    return result
    }

    /// A textual representation of the array and its elements.
    var description: String {
    var result = ""
    queue.sync { result = self.array.description }
    return result
    }
    }

    public extension SynchronizedArray {
    /// Returns the first element of the sequence that satisfies the given predicate or nil if no such element is found.
    ///
    /// - Parameter predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element is a match.
    /// - Returns: The first match or nil if there was no match.
    func first(where predicate: (Element) -> Bool) -> Element? {
    var result: Element?
    queue.sync { result = self.array.first(where: predicate) }
    return result
    }

    /// Returns an array containing, in order, the elements of the sequence that satisfy the given predicate.
    ///
    /// - Parameter isIncluded: A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element should be included in the returned array.
    /// - Returns: An array of the elements that includeElement allowed.
    func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
    var result = [Element]()
    queue.sync { result = self.array.filter(isIncluded) }
    return result
    }

    /// Returns the elements of the collection, sorted using the given predicate as the comparison between elements.
    ///
    /// - Parameter areInIncreasingOrder: A predicate that returns true if its first argument should be ordered before its second argument; otherwise, false.
    /// - Returns: A sorted array of the collection’s elements.
    func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element] {
    var result = [Element]()
    queue.sync { result = self.array.sorted(by: areInIncreasingOrder) }
    return result
    }

    /// Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
    ///
    /// - Parameter transform: A closure that accepts an element of this sequence as its argument and returns an optional value.
    /// - Returns: An array of the non-nil results of calling transform with each element of the sequence.
    func flatMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] {
    var result = [ElementOfResult]()
    queue.sync { result = self.array.flatMap(transform) }
    return result
    }

    /// Calls the given closure on each element in the sequence in the same order as a for-in loop.
    ///
    /// - Parameter body: A closure that takes an element of the sequence as a parameter.
    func forEach(_ body: (Element) -> Void) {
    queue.sync { self.array.forEach(body) }
    }

    /// Returns a Boolean value indicating whether the sequence contains an element that satisfies the given predicate.
    ///
    /// - Parameter predicate: A closure that takes an element of the sequence as its argument and returns a Boolean value that indicates whether the passed element represents a match.
    /// - Returns: true if the sequence contains an element that satisfies predicate; otherwise, false.
    func contains(where predicate: (Element) -> Bool) -> Bool {
    var result = false
    queue.sync { result = self.array.contains(where: predicate) }
    return result
    }
    }

    public extension SynchronizedArray {

    /// Adds a new element at the end of the array.
    ///
    /// - Parameter element: The element to append to the array.
    func append( _ element: Element) {
    queue.async(flags: .barrier) {
    self.array.append(element)
    }
    }

    /// Inserts a new element at the specified position.
    ///
    /// - Parameters:
    /// - element: The new element to insert into the array.
    /// - index: The position at which to insert the new element.
    func insert( _ element: Element, at index: Int) {
    queue.async(flags: .barrier) {
    self.array.insert(element, at: index)
    }
    }

    /// Removes and returns the element at the specified position.
    ///
    /// - Parameters:
    /// - index: The position of the element to remove.
    /// - completion: The handler with the removed element.
    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)
    }
    }
    }

    /// Removes all elements from the array.
    ///
    /// - Parameter completion: The handler with the removed 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 SynchronizedArray {

    /// Accesses the element at the specified position if it exists.
    ///
    /// - Parameter index: The position of the element to access.
    /// - Returns: optional element if it exists.
    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 SynchronizedArray where Element: Equatable {

    /// Returns a Boolean value indicating whether the sequence contains the given element.
    ///
    /// - Parameter element: The element to find in the sequence.
    /// - Returns: true if the element was found in the sequence; otherwise, false.
    func contains(_ element: Element) -> Bool {
    var result = false
    queue.sync { result = self.array.contains(element) }
    return result
    }
    }

    // Thread-unsafe array
    do {
    var array = [Int]()
    var iterations = 1000
    let start = Date().timeIntervalSince1970

    DispatchQueue.concurrentPerform(iterations: iterations) { index in
    let last = array.last ?? 0
    array.append(last + 1)
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Unsafe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count)
    print(message)
    }
    }

    // Thread-safe array
    do {
    var array = SynchronizedArray<Int>()
    var iterations = 1000
    let start = Date().timeIntervalSince1970

    DispatchQueue.concurrentPerform(iterations: iterations) { index in
    let last = array.last ?? 0
    array.append(last + 1)
    iterations -= 1

    // Final loop
    guard iterations <= 0 else { return }
    let message = String(format: "Safe loop took %.3f seconds, count: %d.",
    Date().timeIntervalSince1970 - start,
    array.count)
    print(message)
    }
    }

    PlaygroundPage.current.needsIndefiniteExecution = true