Skip to content

Commit f09d0ce

Browse files
committed
rename
1 parent 65e8957 commit f09d0ce

File tree

8 files changed

+2030
-1774
lines changed

8 files changed

+2030
-1774
lines changed

Evolution/0016-backpressured-stream.md renamed to Evolution/0016-mutli-producer-single-consumer-channel.md

+155-234
Large diffs are not rendered by default.

Sources/AsyncAlgorithms/BackPressuredStream/AsyncBackPressuredStream.swift

-425
This file was deleted.

Sources/AsyncAlgorithms/BackpressuredStream/AsyncNonThrowingBackPressuredStream.swift

-429
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Async Algorithms open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This source file is part of the SwiftCertificates open source project
14+
//
15+
// Copyright (c) 2023 Apple Inc. and the SwiftCertificates project authors
16+
// Licensed under Apache License v2.0
17+
//
18+
// See LICENSE.txt for license information
19+
// See CONTRIBUTORS.txt for the list of SwiftCertificates project authors
20+
//
21+
// SPDX-License-Identifier: Apache-2.0
22+
//
23+
//===----------------------------------------------------------------------===//
24+
25+
/// ``_TinyArray`` is a ``RandomAccessCollection`` optimised to store zero or one ``Element``.
26+
/// It supports arbitrary many elements but if only up to one ``Element`` is stored it does **not** allocate separate storage on the heap
27+
/// and instead stores the ``Element`` inline.
28+
@usableFromInline
29+
struct _TinyArray<Element> {
30+
@usableFromInline
31+
enum Storage {
32+
case one(Element)
33+
case arbitrary([Element])
34+
}
35+
36+
@usableFromInline
37+
var storage: Storage
38+
}
39+
40+
// MARK: - TinyArray "public" interface
41+
42+
extension _TinyArray: Equatable where Element: Equatable {}
43+
extension _TinyArray: Hashable where Element: Hashable {}
44+
extension _TinyArray: Sendable where Element: Sendable {}
45+
46+
extension _TinyArray: RandomAccessCollection {
47+
@usableFromInline
48+
typealias Element = Element
49+
50+
@usableFromInline
51+
typealias Index = Int
52+
53+
@inlinable
54+
subscript(position: Int) -> Element {
55+
get {
56+
self.storage[position]
57+
}
58+
set {
59+
self.storage[position] = newValue
60+
}
61+
}
62+
63+
@inlinable
64+
var startIndex: Int {
65+
self.storage.startIndex
66+
}
67+
68+
@inlinable
69+
var endIndex: Int {
70+
self.storage.endIndex
71+
}
72+
}
73+
74+
extension _TinyArray {
75+
@inlinable
76+
init(_ elements: some Sequence<Element>) {
77+
self.storage = .init(elements)
78+
}
79+
80+
@inlinable
81+
init() {
82+
self.storage = .init()
83+
}
84+
85+
@inlinable
86+
mutating func append(_ newElement: Element) {
87+
self.storage.append(newElement)
88+
}
89+
90+
@inlinable
91+
mutating func append(contentsOf newElements: some Sequence<Element>) {
92+
self.storage.append(contentsOf: newElements)
93+
}
94+
95+
@discardableResult
96+
@inlinable
97+
mutating func remove(at index: Int) -> Element {
98+
self.storage.remove(at: index)
99+
}
100+
101+
@inlinable
102+
mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows {
103+
try self.storage.removeAll(where: shouldBeRemoved)
104+
}
105+
106+
@inlinable
107+
mutating func sort(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows {
108+
try self.storage.sort(by: areInIncreasingOrder)
109+
}
110+
}
111+
112+
// MARK: - TinyArray.Storage "private" implementation
113+
114+
extension _TinyArray.Storage: Equatable where Element: Equatable {
115+
@inlinable
116+
static func == (lhs: Self, rhs: Self) -> Bool {
117+
switch (lhs, rhs) {
118+
case (.one(let lhs), .one(let rhs)):
119+
return lhs == rhs
120+
case (.arbitrary(let lhs), .arbitrary(let rhs)):
121+
// we don't use lhs.elementsEqual(rhs) so we can hit the fast path from Array
122+
// if both arrays share the same underlying storage: https://github.com/apple/swift/blob/b42019005988b2d13398025883e285a81d323efa/stdlib/public/core/Array.swift#L1775
123+
return lhs == rhs
124+
125+
case (.one(let element), .arbitrary(let array)),
126+
(.arbitrary(let array), .one(let element)):
127+
guard array.count == 1 else {
128+
return false
129+
}
130+
return element == array[0]
131+
132+
}
133+
}
134+
}
135+
extension _TinyArray.Storage: Hashable where Element: Hashable {
136+
@inlinable
137+
func hash(into hasher: inout Hasher) {
138+
// same strategy as Array: https://github.com/apple/swift/blob/b42019005988b2d13398025883e285a81d323efa/stdlib/public/core/Array.swift#L1801
139+
hasher.combine(count)
140+
for element in self {
141+
hasher.combine(element)
142+
}
143+
}
144+
}
145+
extension _TinyArray.Storage: Sendable where Element: Sendable {}
146+
147+
extension _TinyArray.Storage: RandomAccessCollection {
148+
@inlinable
149+
subscript(position: Int) -> Element {
150+
get {
151+
switch self {
152+
case .one(let element):
153+
guard position == 0 else {
154+
fatalError("index \(position) out of bounds")
155+
}
156+
return element
157+
case .arbitrary(let elements):
158+
return elements[position]
159+
}
160+
}
161+
set {
162+
switch self {
163+
case .one:
164+
guard position == 0 else {
165+
fatalError("index \(position) out of bounds")
166+
}
167+
self = .one(newValue)
168+
case .arbitrary(var elements):
169+
elements[position] = newValue
170+
self = .arbitrary(elements)
171+
}
172+
}
173+
}
174+
175+
@inlinable
176+
var startIndex: Int {
177+
0
178+
}
179+
180+
@inlinable
181+
var endIndex: Int {
182+
switch self {
183+
case .one: return 1
184+
case .arbitrary(let elements): return elements.endIndex
185+
}
186+
}
187+
}
188+
189+
extension _TinyArray.Storage {
190+
@inlinable
191+
init(_ elements: some Sequence<Element>) {
192+
var iterator = elements.makeIterator()
193+
guard let firstElement = iterator.next() else {
194+
self = .arbitrary([])
195+
return
196+
}
197+
guard let secondElement = iterator.next() else {
198+
// newElements just contains a single element
199+
// and we hit the fast path
200+
self = .one(firstElement)
201+
return
202+
}
203+
204+
var elements: [Element] = []
205+
elements.reserveCapacity(elements.underestimatedCount)
206+
elements.append(firstElement)
207+
elements.append(secondElement)
208+
while let nextElement = iterator.next() {
209+
elements.append(nextElement)
210+
}
211+
self = .arbitrary(elements)
212+
}
213+
214+
@inlinable
215+
init() {
216+
self = .arbitrary([])
217+
}
218+
219+
@inlinable
220+
mutating func append(_ newElement: Element) {
221+
self.append(contentsOf: CollectionOfOne(newElement))
222+
}
223+
224+
@inlinable
225+
mutating func append(contentsOf newElements: some Sequence<Element>) {
226+
switch self {
227+
case .one(let firstElement):
228+
var iterator = newElements.makeIterator()
229+
guard let secondElement = iterator.next() else {
230+
// newElements is empty, nothing to do
231+
return
232+
}
233+
var elements: [Element] = []
234+
elements.reserveCapacity(1 + newElements.underestimatedCount)
235+
elements.append(firstElement)
236+
elements.append(secondElement)
237+
elements.appendRemainingElements(from: &iterator)
238+
self = .arbitrary(elements)
239+
240+
case .arbitrary(var elements):
241+
if elements.isEmpty {
242+
// if `self` is currently empty and `newElements` just contains a single
243+
// element, we skip allocating an array and set `self` to `.one(firstElement)`
244+
var iterator = newElements.makeIterator()
245+
guard let firstElement = iterator.next() else {
246+
// newElements is empty, nothing to do
247+
return
248+
}
249+
guard let secondElement = iterator.next() else {
250+
// newElements just contains a single element
251+
// and we hit the fast path
252+
self = .one(firstElement)
253+
return
254+
}
255+
elements.reserveCapacity(elements.count + newElements.underestimatedCount)
256+
elements.append(firstElement)
257+
elements.append(secondElement)
258+
elements.appendRemainingElements(from: &iterator)
259+
self = .arbitrary(elements)
260+
261+
} else {
262+
elements.append(contentsOf: newElements)
263+
self = .arbitrary(elements)
264+
}
265+
266+
}
267+
}
268+
269+
@discardableResult
270+
@inlinable
271+
mutating func remove(at index: Int) -> Element {
272+
switch self {
273+
case .one(let oldElement):
274+
guard index == 0 else {
275+
fatalError("index \(index) out of bounds")
276+
}
277+
self = .arbitrary([])
278+
return oldElement
279+
280+
case .arbitrary(var elements):
281+
defer {
282+
self = .arbitrary(elements)
283+
}
284+
return elements.remove(at: index)
285+
286+
}
287+
}
288+
289+
@inlinable
290+
mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows {
291+
switch self {
292+
case .one(let oldElement):
293+
if try shouldBeRemoved(oldElement) {
294+
self = .arbitrary([])
295+
}
296+
297+
case .arbitrary(var elements):
298+
defer {
299+
self = .arbitrary(elements)
300+
}
301+
return try elements.removeAll(where: shouldBeRemoved)
302+
303+
}
304+
}
305+
306+
@inlinable
307+
mutating func sort(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows {
308+
switch self {
309+
case .one:
310+
// a collection of just one element is always sorted, nothing to do
311+
break
312+
case .arbitrary(var elements):
313+
defer {
314+
self = .arbitrary(elements)
315+
}
316+
317+
try elements.sort(by: areInIncreasingOrder)
318+
}
319+
}
320+
}
321+
322+
extension Array {
323+
@inlinable
324+
mutating func appendRemainingElements(from iterator: inout some IteratorProtocol<Element>) {
325+
while let nextElement = iterator.next() {
326+
append(nextElement)
327+
}
328+
}
329+
}

0 commit comments

Comments
 (0)