Files
swift-mirror/stdlib/public/Concurrency/Deque/Deque+Extras.swift
2025-02-26 14:28:24 -08:00

187 lines
7.4 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
/// This file is copied from swift-collections and should not be modified here.
/// Rather all changes should be made to swift-collections and copied back.
import Swift
extension _Deque {
/// Creates a deque with the specified capacity, then calls the given
/// closure with a buffer covering the array's uninitialized memory.
///
/// Inside the closure, set the `initializedCount` parameter to the number of
/// elements that are initialized by the closure. The memory in the range
/// `buffer[0..<initializedCount]` must be initialized at the end of the
/// closure's execution, and the memory in the range
/// `buffer[initializedCount...]` must be uninitialized. This postcondition
/// must hold even if the `initializer` closure throws an error.
///
/// - Note: While the resulting deque may have a capacity larger than the
/// requested amount, the buffer passed to the closure will cover exactly
/// the requested number of elements.
///
/// - Parameters:
/// - unsafeUninitializedCapacity: The number of elements to allocate
/// space for in the new deque.
/// - initializer: A closure that initializes elements and sets the count
/// of the new deque.
/// - Parameters:
/// - buffer: A buffer covering uninitialized memory with room for the
/// specified number of elements.
/// - initializedCount: The count of initialized elements in the deque,
/// which begins as zero. Set `initializedCount` to the number of
/// elements you initialize.
init(
unsafeUninitializedCapacity capacity: Int,
initializingWith initializer:
(inout UnsafeMutableBufferPointer<Element>, inout Int) throws -> Void
) rethrows {
self._storage = .init(minimumCapacity: capacity)
try unsafe _storage.update { handle in
unsafe handle.startSlot = .zero
var count = 0
var buffer = unsafe handle.mutableBuffer(for: .zero ..< _Slot(at: capacity))
defer {
precondition(count <= capacity,
"Initialized count set to greater than specified capacity")
let b = unsafe handle.mutableBuffer(for: .zero ..< _Slot(at: capacity))
unsafe precondition(buffer.baseAddress == b.baseAddress && buffer.count == b.count,
"Initializer relocated Deque storage")
unsafe handle.count = count
}
try unsafe initializer(&buffer, &count)
}
}
}
extension _Deque {
/// Removes and returns the first element of this deque, if it exists.
///
/// - Returns: The first element of the original collection if the collection
/// isn't empty; otherwise, `nil`.
///
/// - Complexity: O(1) when this instance has a unique reference to its
/// underlying storage; O(`count`) otherwise.
mutating func popFirst() -> Element? {
// FIXME: Add this to the stdlib on BidirectionalCollection
// where Self == Self.SubSequence
guard count > 0 else { return nil }
_storage.ensureUnique()
return unsafe _storage.update {
unsafe $0.uncheckedRemoveFirst()
}
}
// Note: `popLast` is implemented by the stdlib as a
// `RangeReplaceableCollection` extension, defined in terms of
// `_customRemoveLast`.
/// Adds a new element at the front of the deque.
///
/// Use this method to append a single element to the front of a deque.
///
/// var numbers: Deque = [1, 2, 3, 4, 5]
/// numbers.prepend(100)
/// print(numbers)
/// // Prints "[100, 1, 2, 3, 4, 5]"
///
/// Because deques increase their allocated capacity using an exponential
/// strategy, prepending a single element to a deque is an O(1) operation when
/// averaged over many calls to the `prepend(_:)` method. When a deque has
/// additional capacity and is not sharing its storage with another instance,
/// prepending an element is O(1). When a deque needs to reallocate storage
/// before prepending or its storage is shared with another copy, prepending
/// is O(`count`).
///
/// - Parameter newElement: The element to prepend to the deque.
///
/// - Complexity: Amortized O(1).
///
/// - SeeAlso: `append(_:)`
mutating func prepend(_ newElement: Element) {
_storage.ensureUnique(minimumCapacity: count + 1)
return unsafe _storage.update {
unsafe $0.uncheckedPrepend(newElement)
}
}
/// Adds the elements of a collection to the front of the deque.
///
/// Use this method to prepend the elements of a collection to the front of
/// this deque. This example prepends the elements of a `Range<Int>` instance
/// to a deque of integers.
///
/// var numbers: Deque = [1, 2, 3, 4, 5]
/// numbers.prepend(contentsOf: 10...15)
/// print(numbers)
/// // Prints "[10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5]"
///
/// - Parameter newElements: The elements to prepend to the deque.
///
/// - Complexity: Amortized O(`newElements.count`).
///
/// - SeeAlso: `append(contentsOf:)`
mutating func prepend<C: Collection>(contentsOf newElements: C) where C.Element == Element {
let done: Void? = unsafe newElements._withContiguousStorageIfAvailable_SR14663 { source in
_storage.ensureUnique(minimumCapacity: count + source.count)
unsafe _storage.update { unsafe $0.uncheckedPrepend(contentsOf: source) }
}
guard done == nil else { return }
let c = newElements.count
guard c > 0 else { return }
_storage.ensureUnique(minimumCapacity: count + c)
unsafe _storage.update { target in
let gaps = unsafe target.availableSegments().suffix(c)
unsafe gaps.initialize(from: newElements)
unsafe target.count += c
unsafe target.startSlot = unsafe target.slot(target.startSlot, offsetBy: -c)
}
}
/// Adds the elements of a sequence to the front of the deque.
///
/// Use this method to prepend the elements of a sequence to the front of this
/// deque. This example prepends the elements of a `Range<Int>` instance to a
/// deque of integers.
///
/// var numbers: Deque = [1, 2, 3, 4, 5]
/// numbers.prepend(contentsOf: 10...15)
/// print(numbers)
/// // Prints "[10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5]"
///
/// - Parameter newElements: The elements to prepend to the deque.
///
/// - Complexity: Amortized O(`newElements.count`).
///
/// - SeeAlso: `append(contentsOf:)`
mutating func prepend<S: Sequence>(contentsOf newElements: S) where S.Element == Element {
let done: Void? = unsafe newElements._withContiguousStorageIfAvailable_SR14663 { source in
_storage.ensureUnique(minimumCapacity: count + source.count)
unsafe _storage.update { unsafe $0.uncheckedPrepend(contentsOf: source) }
}
guard done == nil else { return }
let originalCount = self.count
self.append(contentsOf: newElements)
let newCount = self.count
let c = newCount - originalCount
unsafe _storage.update { target in
unsafe target.startSlot = unsafe target.slot(forOffset: originalCount)
unsafe target.count = unsafe target.capacity
unsafe target.closeGap(offsets: c ..< c + (target.capacity - newCount))
unsafe assert(target.count == newCount)
}
}
}