Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncStream & AsyncThrowingStream behavioral divergences & misleading documentation #76547

Open
jamieQ opened this issue Sep 18, 2024 · 0 comments · May be fixed by #76571
Open

AsyncStream & AsyncThrowingStream behavioral divergences & misleading documentation #76547

jamieQ opened this issue Sep 18, 2024 · 0 comments · May be fixed by #76571
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@jamieQ
Copy link
Contributor

jamieQ commented Sep 18, 2024

Description

issues:

  1. AsyncStream supports multiple concurrent consumption, but its documentation states that it does not
  2. AsyncThrowingStream does not support multiple concurrent consumption (its documentation is accurate)

Reproduction

// non-throwing stream
func test_stream() async {
  let (s, c) = AsyncStream<Int>.makeStream()

  let t1 = Task { @MainActor in
    for await _ in s {}
  }
  await MainActor.run {}
  print("installed consumer 1")

  let t2 = Task { @MainActor in
    for await _ in s {}
  }
  await MainActor.run {}
  print("installed consumer 2")
  // works
}

// throwing stream
func test_throwing_stream() async {
  let (s, c) = AsyncThrowingStream<Int, Error>.makeStream()

  let t1 = Task { @MainActor in
    for try await _ in s {}
  }
  await MainActor.run {}
  print("installed consumer 1")

  let t2 = Task { @MainActor in
    for try await _ in s {}
  }
  await MainActor.run {}
  print("installed consumer 2")
  // fatal error shortly after this point
}

Task { await test_stream() }
Task { await test_throwing_stream() }

Expected behavior

the async stream implementations should function analogously with respect to multi-consumption, and the corresponding documentation should accurately reflect their behaviors. in particular, the throwing variant should behave in the same manner that the non-throwing stream does.

Environment

Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

Additional information

relevant forum posts:

  1. https://forums.swift.org/t/consuming-an-asyncstream-from-multiple-tasks-redux/69818
  2. https://forums.swift.org/t/question-how-to-re-introduce-concurrent-iteration-runtime-error-for-asyncstream/71831
@jamieQ jamieQ added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Sep 18, 2024
jamieQ added a commit to jamieQ/swift that referenced this issue Sep 18, 2024
Removes some of the discrepancies between the throwing & non-throwing
variants of AsyncStream. In particular, adds multi-consumer support to
the throwing variant, and updates the docs. Additional minor refactoring
of existing implementation to streamline the code.

Fixes swiftlang#76547
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant