Skip to content

Commit ac79370

Browse files
0xTimLukasa
andauthored
Add ChannelPipeline.SynchronousOperations.Position (#3065)
Adds a new `ChannelPipeline.SynchronousOperations.Position` type to fill a hole in the API that prevented non-sendable Channel handlers being added at a position to the pipeline via the synchronous operations. --------- Co-authored-by: Cory Benfield <[email protected]>
1 parent 08b3b4f commit ac79370

File tree

3 files changed

+486
-27
lines changed

3 files changed

+486
-27
lines changed

Sources/NIOCore/ChannelPipeline.swift

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,14 @@ public final class ChannelPipeline: ChannelInvoker {
176176
let future: EventLoopFuture<Void>
177177

178178
if self.eventLoop.inEventLoop {
179-
future = self.eventLoop.makeCompletedFuture(self.addHandlerSync(handler, name: name, position: position))
179+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
180+
future = self.eventLoop.makeCompletedFuture(
181+
self.addHandlerSync(handler, name: name, position: syncPosition)
182+
)
180183
} else {
181184
future = self.eventLoop.submit {
182-
try self.addHandlerSync(handler, name: name, position: position).get()
185+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
186+
try self.addHandlerSync(handler, name: name, position: syncPosition).get()
183187
}
184188
}
185189

@@ -198,7 +202,7 @@ public final class ChannelPipeline: ChannelInvoker {
198202
fileprivate func addHandlerSync(
199203
_ handler: ChannelHandler,
200204
name: String? = nil,
201-
position: ChannelPipeline.Position = .last
205+
position: ChannelPipeline.SynchronousOperations.Position = .last
202206
) -> Result<Void, Error> {
203207
self.eventLoop.assertInEventLoop()
204208

@@ -1122,11 +1126,12 @@ extension ChannelPipeline {
11221126
_ handlers: [ChannelHandler & Sendable],
11231127
position: ChannelPipeline.Position
11241128
) -> Result<Void, Error> {
1125-
switch position {
1129+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
1130+
switch syncPosition {
11261131
case .first, .after:
1127-
return self._addHandlersSync(handlers.reversed(), position: position)
1132+
return self._addHandlersSync(handlers.reversed(), position: syncPosition)
11281133
case .last, .before:
1129-
return self._addHandlersSync(handlers, position: position)
1134+
return self._addHandlersSync(handlers, position: syncPosition)
11301135
}
11311136
}
11321137

@@ -1143,7 +1148,7 @@ extension ChannelPipeline {
11431148
/// - Returns: A result representing whether the handlers were added or not.
11441149
fileprivate func addHandlersSyncNotSendable(
11451150
_ handlers: [ChannelHandler],
1146-
position: ChannelPipeline.Position
1151+
position: ChannelPipeline.SynchronousOperations.Position
11471152
) -> Result<Void, Error> {
11481153
switch position {
11491154
case .first, .after:
@@ -1162,7 +1167,7 @@ extension ChannelPipeline {
11621167
/// - Returns: A result representing whether the handlers were added or not.
11631168
private func _addHandlersSync<Handlers: Sequence>(
11641169
_ handlers: Handlers,
1165-
position: ChannelPipeline.Position
1170+
position: ChannelPipeline.SynchronousOperations.Position
11661171
) -> Result<Void, Error> where Handlers.Element == ChannelHandler & Sendable {
11671172
self.eventLoop.assertInEventLoop()
11681173

@@ -1191,7 +1196,7 @@ extension ChannelPipeline {
11911196
/// - Returns: A result representing whether the handlers were added or not.
11921197
private func _addHandlersSyncNotSendable<Handlers: Sequence>(
11931198
_ handlers: Handlers,
1194-
position: ChannelPipeline.Position
1199+
position: ChannelPipeline.SynchronousOperations.Position
11951200
) -> Result<Void, Error> where Handlers.Element == ChannelHandler {
11961201
self.eventLoop.assertInEventLoop()
11971202

@@ -1238,20 +1243,67 @@ extension ChannelPipeline {
12381243
public func addHandler(
12391244
_ handler: ChannelHandler,
12401245
name: String? = nil,
1241-
position: ChannelPipeline.Position = .last
1246+
position: ChannelPipeline.SynchronousOperations.Position = .last
12421247
) throws {
12431248
try self._pipeline.addHandlerSync(handler, name: name, position: position).get()
12441249
}
12451250

1251+
/// Add a handler to the pipeline.
1252+
///
1253+
/// - Important: This *must* be called on the event loop.
1254+
/// - Parameters:
1255+
/// - handler: The handler to add.
1256+
/// - name: The name to use for the `ChannelHandler` when it's added. If no name is specified the one will be generated.
1257+
/// - position: The position in the `ChannelPipeline` to add `handler`. Defaults to `.last`.
1258+
@available(*, deprecated, message: "Use ChannelPipeline.SynchronousOperations.Position instead")
1259+
@_disfavoredOverload
1260+
public func addHandler(
1261+
_ handler: ChannelHandler,
1262+
name: String? = nil,
1263+
position: ChannelPipeline.Position = .last
1264+
) throws {
1265+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
1266+
try self._pipeline.addHandlerSync(handler, name: name, position: syncPosition).get()
1267+
}
1268+
1269+
/// Add an array of handlers to the pipeline.
1270+
///
1271+
/// - Important: This *must* be called on the event loop.
1272+
/// - Parameters:
1273+
/// - handlers: The handlers to add.
1274+
/// - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.
1275+
public func addHandlers(
1276+
_ handlers: [ChannelHandler],
1277+
position: ChannelPipeline.SynchronousOperations.Position = .last
1278+
) throws {
1279+
try self._pipeline.addHandlersSyncNotSendable(handlers, position: position).get()
1280+
}
1281+
12461282
/// Add an array of handlers to the pipeline.
12471283
///
12481284
/// - Important: This *must* be called on the event loop.
12491285
/// - Parameters:
12501286
/// - handlers: The handlers to add.
12511287
/// - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.
1288+
@available(*, deprecated, message: "Use ChannelPipeline.SynchronousOperations.Position instead")
1289+
@_disfavoredOverload
12521290
public func addHandlers(
12531291
_ handlers: [ChannelHandler],
12541292
position: ChannelPipeline.Position = .last
1293+
) throws {
1294+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
1295+
try self._pipeline.addHandlersSyncNotSendable(handlers, position: syncPosition).get()
1296+
}
1297+
1298+
/// Add one or more handlers to the pipeline.
1299+
///
1300+
/// - Important: This *must* be called on the event loop.
1301+
/// - Parameters:
1302+
/// - handlers: The handlers to add.
1303+
/// - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.
1304+
public func addHandlers(
1305+
_ handlers: ChannelHandler...,
1306+
position: ChannelPipeline.SynchronousOperations.Position = .last
12551307
) throws {
12561308
try self._pipeline.addHandlersSyncNotSendable(handlers, position: position).get()
12571309
}
@@ -1262,11 +1314,14 @@ extension ChannelPipeline {
12621314
/// - Parameters:
12631315
/// - handlers: The handlers to add.
12641316
/// - position: The position in the `ChannelPipeline` to add `handlers`. Defaults to `.last`.
1317+
@available(*, deprecated, message: "Use ChannelPipeline.SynchronousOperations.Position instead")
1318+
@_disfavoredOverload
12651319
public func addHandlers(
12661320
_ handlers: ChannelHandler...,
12671321
position: ChannelPipeline.Position = .last
12681322
) throws {
1269-
try self._pipeline.addHandlersSyncNotSendable(handlers, position: position).get()
1323+
let syncPosition = ChannelPipeline.SynchronousOperations.Position(position)
1324+
try self._pipeline.addHandlersSyncNotSendable(handlers, position: syncPosition).get()
12701325
}
12711326

12721327
/// Remove a `ChannelHandler` from the `ChannelPipeline`.
@@ -1574,6 +1629,41 @@ extension ChannelPipeline {
15741629
}
15751630
}
15761631

1632+
extension ChannelPipeline.SynchronousOperations {
1633+
/// A `Position` within the `ChannelPipeline`'s `SynchronousOperations` used to insert non-sendable handlers
1634+
/// into the `ChannelPipeline` at a certain position.
1635+
public enum Position {
1636+
/// The first `ChannelHandler` -- the front of the `ChannelPipeline`.
1637+
case first
1638+
1639+
/// The last `ChannelHandler` -- the back of the `ChannelPipeline`.
1640+
case last
1641+
1642+
/// Before the given `ChannelHandler`.
1643+
case before(ChannelHandler)
1644+
1645+
/// After the given `ChannelHandler`.
1646+
case after(ChannelHandler)
1647+
1648+
public init(_ position: ChannelPipeline.Position) {
1649+
switch position {
1650+
case .first:
1651+
self = .first
1652+
case .last:
1653+
self = .last
1654+
case .before(let handler):
1655+
self = .before(handler)
1656+
case .after(let handler):
1657+
self = .after(handler)
1658+
}
1659+
}
1660+
}
1661+
}
1662+
1663+
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
1664+
@available(*, unavailable)
1665+
extension ChannelPipeline.SynchronousOperations.Position: Sendable {}
1666+
15771667
/// Special `ChannelHandler` that forwards all events to the `Channel.Unsafe` implementation.
15781668
final class HeadChannelHandler: _ChannelOutboundHandler, Sendable {
15791669

0 commit comments

Comments
 (0)