Skip to content

Commit 25ce8b2

Browse files
committed
Simplify iterator sharing cycle
1 parent 82f09ef commit 25ce8b2

1 file changed

Lines changed: 18 additions & 27 deletions

File tree

Sources/NIOHTTPServer/HTTPRequestConcludingAsyncReader.swift

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,20 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
6060
}
6161

6262
private var state: State
63+
private var readerState: ReaderState
6364

6465
/// The iterator that provides HTTP request parts from the underlying channel.
6566
/// Taken from ReaderState once at the start of reading, and returned when reading completes.
6667
private var iterator: NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator?
6768

68-
init(iterator: NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator?) {
69+
init(readerState: ReaderState) {
6970
self.state = .readingBody(.noExcess)
70-
self.iterator = iterator
71+
self.readerState = readerState
72+
self.iterator = readerState.takeIterator()
7173
}
7274

7375
enum ReadResult {
7476
case readBody(ByteBuffer)
75-
case readEnd(HTTPFields?)
7677
case requestFinished
7778
}
7879

@@ -103,7 +104,14 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
103104

104105
case .end(let trailers):
105106
self.state = .finished
106-
return .readEnd(trailers)
107+
nonisolated(unsafe) let iterator = self.iterator.take()
108+
self.readerState.wrapped.withLock { state in
109+
state.finishedReading = true
110+
state.trailers = trailers
111+
let disconnected = Disconnected(value: iterator)
112+
state.iterator = disconnected.take()
113+
}
114+
return .requestFinished
107115
}
108116
}
109117

@@ -123,11 +131,6 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
123131
return .requestFinished
124132
}
125133
}
126-
127-
/// Takes the iterator out of the state machine for recovery.
128-
mutating func takeIterator() -> NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator? {
129-
self.iterator.take()
130-
}
131134
}
132135

133136
var requestBodyStateMachine: RequestBodyStateMachine
@@ -136,8 +139,7 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
136139
///
137140
/// Takes the iterator from ReaderState so the state machine owns it for the entire read cycle.
138141
fileprivate init(readerState: ReaderState) {
139-
let iterator = readerState.takeIterator()
140-
self.requestBodyStateMachine = .init(iterator: iterator)
142+
self.requestBodyStateMachine = .init(readerState: readerState)
141143
self.state = readerState
142144
}
143145

@@ -163,16 +165,6 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
163165
case .readBody(let readElement):
164166
return try await body(Array(buffer: readElement).span)
165167

166-
case .readEnd(let trailers):
167-
// Reading is complete. Return the iterator to ReaderState.
168-
nonisolated(unsafe) let iterator = self.requestBodyStateMachine.takeIterator()
169-
self.state.wrapped.withLock { state in
170-
state.trailers = trailers
171-
state.finishedReading = true
172-
state.iterator = Disconnected(value: iterator)
173-
}
174-
return try await body(.init())
175-
176168
case .requestFinished:
177169
return try await body(.init())
178170
}
@@ -189,21 +181,20 @@ public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable
189181

190182
/// The iterator that provides HTTP request parts from the underlying channel.
191183
/// Stored here between read cycles for HTTP/1.1 keep-alive recovery.
192-
var iterator:
193-
Disconnected<
194-
NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator?
195-
>
184+
var iterator: NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator?
196185
}
197186

198187
let wrapped: Mutex<Wrapped>
199188

200189
init(iterator: consuming sending NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator) {
201-
self.wrapped = .init(.init(iterator: Disconnected(value: iterator)))
190+
self.wrapped = .init(.init(iterator: iterator))
202191
}
203192

204193
func takeIterator() -> sending NIOAsyncChannelInboundStream<HTTPRequestPart>.AsyncIterator? {
205194
self.wrapped.withLock { state in
206-
state.iterator.swap(newValue: nil)
195+
let iterator = state.iterator
196+
state.iterator = nil
197+
return iterator
207198
}
208199
}
209200
}

0 commit comments

Comments
 (0)