Files
swift-mirror/stdlib/public/Concurrency/AsyncIteratorProtocol.swift
Karoy Lorentey 47956908b7 [Concurrency] SwiftStdlib 5.5 ⟹ SwiftStdlib 5.1 (usages)
The concurrency runtime now deploys back to macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, which corresponds to the 5.1 release of the stdlib.

Adjust macro usages accordingly.
2021-10-28 14:36:36 -07:00

98 lines
3.8 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Swift
/// A type that that asychronously supplies the values of a sequence one at a
/// time.
///
/// The `AsyncIteratorProtocol` defines the type returned by the
/// `makeAsyncIterator()` method of the `AsyncSequence` protocol. In short,
/// the iterator is what produces the asynchronous sequence's values. The
/// protocol defines a single asynchronous method, `next()`, which either
/// produces the next element of the sequence, or returns `nil` to signal
/// the end of the sequence.
///
/// To implement your own `AsyncSequence`, implement a wrapped type that
/// conforms to `AsyncIteratorProtocol`. The following example shows a `Counter`
/// type that uses an inner iterator to monotonically generate `Int` values
/// until reaching a `howHigh` value. While this example isn't itself
/// asychronous, it shows the shape of a custom sequence and iterator, and how
/// to use it as if it were asynchronous:
///
/// struct Counter : AsyncSequence {
/// typealias Element = Int
/// let howHigh: Int
///
/// struct AsyncIterator : AsyncIteratorProtocol {
/// let howHigh: Int
/// var current = 1
/// mutating func next() async -> Int? {
/// // A genuinely asychronous implementation uses the `Task`
/// // API to check for cancellation here and return early.
/// guard current <= howHigh else {
/// return nil
/// }
///
/// let result = current
/// current += 1
/// return result
/// }
/// }
///
/// func makeAsyncIterator() -> AsyncIterator {
/// return AsyncIterator(howHigh: howHigh)
/// }
/// }
///
/// At the call site, this looks like:
///
/// for await i in Counter(howHigh: 10) {
/// print(i, terminator: " ")
/// }
/// // Prints: 1 2 3 4 5 6 7 8 9 10
///
/// ### End of Iteration
///
/// The iterator returns `nil` to indicate the end of the sequence. After
/// returning `nil` (or throwing an error) from `next()`, the iterator enters
/// a terminal state, and all future calls to `next()` must return `nil`.
///
/// ### Cancellation
///
/// Types conforming to `AsyncIteratorProtocol` should use the cancellation
/// primitives provided by Swift's `Task` API. The iterator can choose how to
/// handle and respond to cancellation, including:
///
/// - Checking the `isCancelled` value of the current `Task` inside `next()`
/// and returning `nil` to terminate the sequence.
/// - Calling `checkCancellation()` on the `Task`, which throws a
/// `CancellationError`.
/// - Implementing `next()` with a
/// `withTaskCancellationHandler(handler:operation:)` invocation to
/// immediately react to cancellation.
///
/// If the iterator needs to clean up on cancellation, it can do so after
/// checking for cancellation as described above, or in `deinit` if it's
/// a reference type.
@available(SwiftStdlib 5.1, *)
@rethrows
public protocol AsyncIteratorProtocol {
associatedtype Element
/// Asynchronously advances to the next element and returns it, or ends the
/// sequence if there is no next element.
///
/// - Returns: The next element, if it exists, or `nil` to signal the end of
/// the sequence.
mutating func next() async throws -> Element?
}