Repository: apple/swift
File: stdlib/public/Concurrency/AsyncThrowingStream.swift (Swift)

Code before:
    /// - Parameter error: The error to throw, or `nil`, to finish normally.
    ///
    /// Calling this function more than once has no effect. After calling
    /// finish, the stream enters a terminal state and doesn't produce any additional
    /// elements.
    public func finish(throwing error: __owned Failure? = nil) {
      storage.finish(throwing: error)
    }

    /// A callback to invoke when canceling iteration of an asynchronous
    /// stream.
    ///
    /// If an `onTermination` callback is set, using task cancellation to
    /// terminate iteration of an `AsyncThrowingStream` results in a call to this
    /// callback.
    ///
    /// Canceling an active iteration invokes the `onTermination` callback
    /// first, and then resumes by yielding `nil` or throwing an error from the
    /// iterator. This means that you can perform needed cleanup in the
    ///  cancellation handler. After reaching a terminal state, the
    ///  `AsyncThrowingStream` disposes of the callback.
    ///
    ///  - Note: The `onTermination` callback may be invoked synchronously as part
    ///  of task cancellation. As such, it is subject to similar considerations for
    ///  avoiding deadlock as outlined in the documentation for
    ///  ``withTaskCancellationHandler(operation:onCancel:)``.
    public var onTermination: (@Sendable (Termination) -> Void)? {
      get {
        return storage.getOnTermination()
      }
      nonmutating set {
        storage.setOnTermination(newValue)
      }
    }
  }

  final class _Context {
    let storage: _Storage?
    let produce: () async throws(Failure) -> Element?

    init(storage: _Storage? = nil, produce: @escaping () async throws(Failure) -> Element?) {
      self.storage = storage
      self.produce = produce
    }

    deinit {
      storage?.cancel()
    }
  }

  let context: _Context

Review comment (bug):
As above:


```suggestion

    ///  - Note: Because the system might call the `onTermination` callback synchronously, as part
    ///  of task cancellation, it's subject to similar considerations for
    ///  avoiding deadlock as outlined in the documentation for
    ///  ``withTaskCancellationHandler(operation:onCancel:)``.
```

Code after:
    /// - Parameter error: The error to throw, or `nil`, to finish normally.
    ///
    /// Calling this function more than once has no effect. After calling
    /// finish, the stream enters a terminal state and doesn't produce any additional
    /// elements.
    public func finish(throwing error: __owned Failure? = nil) {
      storage.finish(throwing: error)
    }

    /// A callback to invoke when canceling iteration of an asynchronous
    /// stream.
    ///
    /// If an `onTermination` callback is set, using task cancellation to
    /// terminate iteration of an `AsyncThrowingStream` results in a call to this
    /// callback.
    ///
    /// Canceling an active iteration invokes the `onTermination` callback
    /// first, and then resumes by yielding `nil` or throwing an error from the
    /// iterator. This means that you can perform needed cleanup in the
    ///  cancellation handler. After reaching a terminal state, the
    ///  `AsyncThrowingStream` disposes of the callback.
    ///
    /// - Note: Because the system might call the `onTermination` callback as
    /// part of task cancellation, it's subject to the same considerations for
    /// avoiding deadlock as outlined in the documentation for
    /// ``withTaskCancellationHandler(operation:onCancel:)``.
    public var onTermination: (@Sendable (Termination) -> Void)? {
      get {
        return storage.getOnTermination()
      }
      nonmutating set {
        storage.setOnTermination(newValue)
      }
    }
  }

  final class _Context {
    let storage: _Storage?
    let produce: () async throws(Failure) -> Element?

    init(storage: _Storage? = nil, produce: @escaping () async throws(Failure) -> Element?) {
      self.storage = storage
      self.produce = produce
    }

    deinit {
      storage?.cancel()
    }
  }

  let context: _Context