Skip to content

Support bounded channel with bound of 0 (rendezvous) #116097

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

Merged
merged 2 commits into from
Jun 3, 2025

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented May 29, 2025

Closes #94046.

This PR enables Channel.CreateBounded(0), whereas currently a bound of < 1 is exceptional. A bound is the number of items the channel can buffer, so a bound of 0 means it can't buffer anything, which makes it into a rendezvous, where the reader and writer must be at the channel at the same time in order to directly hand off from the writer to the reader. This is the same meaning as in other languages/libraries, e.g. if in go you don't specify a bound or you specify a bound of 0, you similarly get an unbuffered rendezvous channel.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces support for rendezvous channels by allowing a bounded capacity of 0, which creates an unbuffered channel where writers and readers synchronize directly. In addition to updating the channel‐creation logic and validations, the PR adds new tests (including RendezvousChannelTests) and modernizes null checks throughout the code.

  • Support for rendezvous channels in CreateBounded by treating capacity==0 differently.
  • Updated validations in ChannelOptions and related APIs to accept capacity 0.
  • New test coverage for unbuffered channels and consistent use of null-check patterns.

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
TestBase.cs Added a new ThreeBools property used in test data generation.
System.Threading.Channels.Tests.csproj Added the RendezvousChannelTests.cs file to the project.
Stress.cs Introduced new test cases for the rendezvous channel scenario.
RendezvousChannelTests.cs New test suite verifying the behavior of unbuffered (rendezvous) channels.
ChannelTests.cs Modified tests to reflect the updated capacity validation (negative values only are invalid).
Channel.cs & ChannelOptions.cs Updated channel creation methods and validations to allow capacity == 0, creating a rendezvous channel.
BoundedChannel.cs, UnboundedChannel.cs, SingleConsumerUnboundedChannel.cs Updated null-check style and refined internal logic for consistency.
ChannelUtilities.* & AsyncOperation.* Modernized helper methods and cancellation callbacks with updated null-checks.
SingleProducerSingleConsumerQueue.cs Updated debug assertions using the new null-check style.
Comments suppressed due to low confidence (3)

src/libraries/System.Threading.Channels/tests/RendezvousChannelTests.cs:23

  • [nitpick] The tests for the rendezvous channel cover core behaviors; consider adding additional cancellation tests specific to unbuffered channels to ensure robust behavior under cancellation conditions.
Channel<int> c = CreateChannel<int>();

src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs:40

  • Please confirm that changing the capacity validation to support capacity == 0 for rendezvous channels has been fully tested, as this alters the API behavior by allowing unbuffered channels.
public static Channel<T> CreateBounded<T>(int capacity) =>

src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs:70

  • The updated validation for Capacity now permits a value of 0; please ensure that the documentation reflects that a capacity of 0 indicates a rendezvous channel.
if (value < 0)

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for zero-capacity (rendezvous) bounded channels by routing CreateBounded(0) to a new RendezvousChannel implementation, updates validation to allow zero bounds, and introduces tests covering rendezvous behavior.

  • Update Channel.CreateBounded to handle capacity == 0
  • Add RendezvousChannel implementation and extensive rendezvous tests
  • Adjust options validation and test code for asynchronous writes

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs Routes capacity == 0 to RendezvousChannel
src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs Changed capacity check to allow 0; updated exception docs
src/libraries/System.Threading.Channels/tests/RendezvousChannelTests.cs New tests for rendezvous channels
src/libraries/System.Threading.Channels/tests/Stress.cs Added rendezvous stress test variations
src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelUtilities.cs Added unused CountOperations helper
Comments suppressed due to low confidence (2)

src/libraries/System.Threading.Channels/tests/Stress.cs:65

  • Rendezvous tests currently only cover Wait and DropWrite modes. Consider adding DropOldest and DropNewest to ensure full-mode behaviors are validated for zero-capacity channels.
foreach (var bcfm in new[] { BoundedChannelFullMode.Wait, BoundedChannelFullMode.DropWrite })

src/libraries/System.Threading.Channels/tests/Stress.cs:65

  • [nitpick] The local variable bcfm is abbreviated and may not convey its purpose clearly. Consider renaming it to fullMode for readability.
foreach (var bcfm in new[] { BoundedChannelFullMode.Wait, BoundedChannelFullMode.DropWrite })

This PR enables Channel.CreateBounded(0), whereas currently a bound of < 1 is exceptional. A bound is the number of items the channel can buffer, so a bound of 0 means it can't buffer anything, which makes it into a rendezvous, where the reader and writer must be at the channel at the same time in order to directly hand off from the writer to the reader. This is the same meaning as in other languages/libraries, e.g. if in go you don't specify a bound or you specify a bound of 0, you similarly get an unbuffered rendezvous channel.
@stephentoub
Copy link
Member Author

/ba-g unrelated test infra failure

@stephentoub stephentoub merged commit fcd197c into dotnet:main Jun 3, 2025
84 of 86 checks passed
@stephentoub stephentoub deleted the bounded0 branch June 3, 2025 03:27
@davidfowl
Copy link
Member

We brought back unbuffered channels?! Nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add rendezvous channel without buffer
3 participants