Channel Types - fthoms/jiminy GitHub Wiki

Channel Types

There are two types of channels: buffered and unbuffered.

Unbuffered Channels

An unbuffered channel has blocking send and receive primitives. That means sending a message will block until there is a receiver on the other end ready to process the message. This is illustrated in the following test:

[Fact(DisplayName = "Blocking receive blocks until there is a message")]
void blocking_receice_blocks_until_message() {
    var chan = Channel.Make<Guid>();
    var messageSent = false;
    var sender = Task.Run(() =>
    {
        Task.Delay(100).Wait();
        chan.Send(Guid.NewGuid());
        messageSent = true;
    });
    messageSent.ShouldBeFalse();
    var (msg, error) = chan.Receive();
    sender.Wait();
    messageSent.ShouldBeTrue();
}

There is also a nonblocking send which will deliver the message if there is a receiver for it, otherwise a default action is invoked.

[Fact(DisplayName = "Nonblocking send invokes default handler if there is no receiver")]
void nonblocking_send_invokes_default_if_no_receiver() {
    var chan = Channel.Make<int>();
    var defaultInvoked = false;
    var error = chan.Send(1, () => defaultInvoked = true);
    error.ShouldBeNull();
    defaultInvoked.ShouldBeTrue();
}

Buffered Channels

Buffered channels are created by specifying a buffer limit in the channel factory method:

Channel.Make<int>(10);

Buffered channels accept messages even though there are no receivers ready on the other end, up until the buffer limit is reached, as illustrated in the following test:

[Fact(DisplayName = "Blocking send blocks if buffer limit has been exceeded until a slot is released")]
void blocking_send_blocks_on_buffer_limit() {
    var chan = Channel.Make<int>(1);
    var secondSendComplete = false;
    chan.Send(1);
    var sender = Task.Run(() =>
    {
        chan.Send(2);
        secondSendComplete = true;
    });
    Task.Delay(100).Wait();
    secondSendComplete.ShouldBeFalse();
    (sender.IsCanceled || sender.IsCompleted || sender.IsFaulted).ShouldBeFalse();
    //release the second send by receiving a value
    chan.Receive();
    sender.Wait();
    secondSendComplete.ShouldBeTrue();
}

The following example code illustrates how the buffered channel does not block if the limit has not been reached. It also illustrates a crucial point: messages are not lost, even though a channel is closed.

sealed class ChannelBuffering : IExample {
    public void Run() {
        var messages = Channel.Make<string>(2);

        messages.Send("buffered");
        messages.Send("channel");

        messages.Close();

        Console.WriteLine(messages.Receive().Message);
        Console.WriteLine(messages.Receive().Message);
    }
}

This produces the following output:

buffered
channel
Press any key to continue . . .
⚠️ **GitHub.com Fallback** ⚠️