Skip to content

Commit 05e3c55

Browse files
authored
Merge pull request #61577 from apple/egorzhdan/cxx-iterator-boxing
[cxx-interop] Optimize `CxxIterator` and `CxxSequence`
2 parents aa82a76 + 10b7057 commit 05e3c55

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

stdlib/public/Cxx/CxxSequence.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,27 +80,39 @@ public protocol CxxSequence: Sequence {
8080
mutating func __endUnsafe() -> RawIterator
8181
}
8282

83-
public class CxxIterator<T>: IteratorProtocol where T: CxxSequence {
84-
// Declared as a class instead of a struct to avoid copies of this object,
85-
// which would result in dangling pointers for some C++ sequence types.
83+
/// Prevents a C++ sequence from being copied or moved implicitly. Makes sure
84+
/// that raw C++ iterators pointing into the sequence are not invalidated.
85+
@usableFromInline
86+
internal final class CxxSequenceBox<T> where T: CxxSequence {
87+
@usableFromInline
88+
internal var sequence: T
89+
90+
@usableFromInline
91+
internal init(_ sequence: __shared T) {
92+
self.sequence = sequence
93+
}
94+
}
8695

96+
@frozen
97+
public struct CxxIterator<T>: IteratorProtocol where T: CxxSequence {
8798
public typealias Element = T.RawIterator.Pointee
8899

89100
@usableFromInline
90-
internal var sequence: T
101+
internal let sequence: CxxSequenceBox<T>
91102
@usableFromInline
92103
internal var rawIterator: T.RawIterator
93104
@usableFromInline
94105
internal let endIterator: T.RawIterator
95106

96-
public init(sequence: T) {
97-
self.sequence = sequence
98-
self.rawIterator = self.sequence.__beginUnsafe()
99-
self.endIterator = self.sequence.__endUnsafe()
107+
@inlinable
108+
public init(sequence: __shared T) {
109+
self.sequence = CxxSequenceBox<T>(sequence)
110+
self.rawIterator = self.sequence.sequence.__beginUnsafe()
111+
self.endIterator = self.sequence.sequence.__endUnsafe()
100112
}
101113

102114
@inlinable
103-
public func next() -> Element? {
115+
public mutating func next() -> Element? {
104116
if self.rawIterator == self.endIterator {
105117
return nil
106118
}

0 commit comments

Comments
 (0)