Channel Types - fthoms/jiminy GitHub Wiki
There are two types of channels: buffered and unbuffered.
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 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 . . .