Description
Background and motivation
Problem
let ch = Channel.CreateBounded 1
ch.Write "hi"
Console.WriteLine "consumer received"
The problem is - the last line is a lie, there is no guarantee neither that the consumer received anything, nor there is a consumer in the first place all because that channel has a BUFFER.
Reference
Channels are messaging primitives allowing processes/actors/threads/fiber/jobs/tasks to communicate and synchronize their work and data flow.
Synchronization is achieved by blocking both consumer and receiver until they are ready to communicate and pass data between each other. This is actually a default behaviour of channels in theory (pi-calculus) and practice (Go, Kotlin, F# Hopac, CML)
The problem above is solved in Go precisely as described because default Go channels don't have any buffer and they will block the producer until the consumer is ready and vice versa.
In Kotlin it is achieved by creating Channel with capacity = 0
In .NET you can't create BoundedChannel
with capacity=0
- because capacity can't be lower than 1
- even if we could, it will be UB what will happen with capacity=0 and
BoundedChannelFullMode
other thanWait
So I propose to add
Channel.CreateRendezvous()
which will create a channel without any buffers to achieve messaging synchronization and probably some selective messaging (e.g. read multiple channels, read 1, leave all others intact)
API Proposal
namespace System.Threading.Channels;
public static class Channel
{
public static Channel<T> CreateRendezvous<T>(RendezvousChannelOptions options)
}
API Usage
let fancyChannel = Channel.CreateRendezvous()
do! fancyChannel.WriteAsync 42 // blocked until consumer is ready
Console.WriteLine "consumer received our message!" // not a lie as we know it definitely received
Alternative Designs
Make BoundedChannel work with capacity=0
Risks
N/A