-
Notifications
You must be signed in to change notification settings - Fork 634
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement a `NIOAsyncWriter` # Motivation We previously added the `NIOAsyncProducer` to bridge between the NIO channel pipeline and the asynchronous world. However, we still need something to bridge writes from the asynchronous world back to the NIO channel pipeline. # Modification This PR adds a new `NIOAsyncWriter` type that allows us to asynchronously `yield` elements to it. On the other side, we can register a `NIOAsyncWriterDelegate` which will get informed about any written elements. Furthermore, the synchronous side can toggle the writability of the `AsyncWriter` which allows it to implement flow control. A main goal of this type is to be as performant as possible. To achieve this I did the following things: - Make everything generic and inlinable - Use a class with a lock instead of an actor - Provide methods to yield a sequence of things which allows users to reduce the amount of times the lock gets acquired. # Result We now have the means to bridge writes from the asynchronous world to the synchronous * Remove the completion struct and incorporate code review comments * Fixup some refactoring leftovers * More code review comments * Move to holding the lock around the delegate and moved the delegate into the state machine * Comment fixups * More doc fixes * Call finish when the sink deinits * Refactor the writer to only yield Deques and rename the delegate to NIOAsyncWriterSinkDelegate * Review * Fix some warnings * Fix benchmark sendability * Remove Failure generic parameter and allow sending of an error through the Sink
- Loading branch information
1 parent
26afcec
commit f144292
Showing
9 changed files
with
1,738 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,060 changes: 1,060 additions & 0 deletions
1,060
Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
Sources/NIOPerformanceTester/NIOAsyncWriterSingleWritesBenchmark.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftNIO open source project | ||
// | ||
// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#if compiler(>=5.5.2) && canImport(_Concurrency) | ||
import NIOCore | ||
import DequeModule | ||
import Atomics | ||
|
||
struct NoOpDelegate: NIOAsyncWriterSinkDelegate, @unchecked Sendable { | ||
typealias Element = Int | ||
let counter = ManagedAtomic(0) | ||
|
||
func didYield(contentsOf sequence: Deque<Int>) { | ||
counter.wrappingIncrement(by: sequence.count, ordering: .relaxed) | ||
} | ||
|
||
func didTerminate(error: Error?) {} | ||
} | ||
|
||
// This is unchecked Sendable because the Sink is not Sendable but the Sink is thread safe | ||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) | ||
final class NIOAsyncWriterSingleWritesBenchmark: AsyncBenchmark, @unchecked Sendable { | ||
private let iterations: Int | ||
private let delegate: NoOpDelegate | ||
private let writer: NIOAsyncWriter<Int, NoOpDelegate> | ||
private let sink: NIOAsyncWriter<Int, NoOpDelegate>.Sink | ||
|
||
init(iterations: Int) { | ||
self.iterations = iterations | ||
self.delegate = .init() | ||
let newWriter = NIOAsyncWriter<Int, NoOpDelegate>.makeWriter(isWritable: true, delegate: self.delegate) | ||
self.writer = newWriter.writer | ||
self.sink = newWriter.sink | ||
} | ||
|
||
func setUp() async throws {} | ||
func tearDown() {} | ||
|
||
func run() async throws -> Int { | ||
for i in 0..<self.iterations { | ||
try await self.writer.yield(i) | ||
} | ||
return self.delegate.counter.load(ordering: .sequentiallyConsistent) | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.