Channel#receive vs Channel#receive? differs on their behavior for closed channels. Using them directly is always blocking.
Performing an operation over a closed and closing the channel during the operation must behave in the same way.
Given a ch : Channel(T), ch2 : Channel(T2):
m = ch.receiveselect
when m = ch.receive
endi, m = Channel.select(ch.receive_select_action)i : Int32,m : T- will suspend current fiber if there are no pending messages in
ch - if
chwas closed, or is closed while fiber is suspended, it will raiseClosedError - on
ch.send(t),i == 0 && m == t
select
when m = ch.receive
else
endm : T- will execute
elseblock if there are no pending messages inch - if channel was closed will raise
ClosedError- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended.
- on
ch.send(t),m == t, execute firstwhenblock.
i, m = Channel.non_blocking_select(ch.receive_select_action)i : Int32,m : T | NotReadyi == 1 && m == NotReadyif there are no pending messages inch- if any
chwas closed, it will raiseClosedError- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended.
select
when m = ch.receive
when m2 = ch2.receive
endm : T,m2 : T2- if non of the channel has messages, the current fiber will be suspended.
- if any
chorch2was or is closed, the select will raiseClosedError - on
ch.send(t),m == t, execute firstwhenblock. - on
ch2.send(t),m2 == t, execute secondwhenblock.
i, m = Channel.select(ch.receive_select_action, ch2.receive_select_action)i : Int32,m : T | T2- will suspend current fiber if there are no pending messages in neither
chnorch2 - if any
chorch2was closed, or is closed while fiber is suspended, it will raiseClosedError
select
when m1 = ch.receive
when m2 = ch2.receive
else
endm : T,m2 : T2- if any
chorch2was closed, the select will raiseClosedError- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended.
- if non of the channel has messages, the
elseblock will execute.
m = ch.receive?select
when m = ch.receive?
endi, m = Channel.select(ch.receive_select_action?)i : Int32,m : T | Nil- will suspend current fiber if there are no pending messages in
ch - if channel was closed (or is closed while fiber is suspended)
i == 0 && m == nil
select
when m1 = ch.receive?
when m2 = ch2.receive?
endm1 : T1 | Nil,m2 : T2 | Nil- will suspend current fiber if there are no pending messages in neither
chnorch2 - if channel was closed (or is closed while fiber is suspended)
i == 0 && m1 == nil(forch) ori == 1 && m2 == nil(forch2)- Note: if there are many channels closed, then one of them will be picked.
i, m = Channel.select(ch.receive_select_action?, ch2.receive_select_action?)i : Int32,m : T | T2 | Nil- will suspend current fiber if there are no pending messages in neither
chnorch2 - if channel was closed (or is closed while fiber is suspended)
i == 0 && m == nil(forch) ori == 1 && m == nil(forch2)- Note: if there are many channels closed, then one of them will be picked.
select
when m = ch.receive?
else
endi, m = Channel.non_blocking_select(ch.receive_select_action?)i : Int32,m : T | Nil | NotReadym == NotReadyif there are no pending messages inchm == nilif channel was closed- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended
select
when m = ch.receive?
when m2 = ch2.receive?
else
endm : T | Nil,m2 : T2 | Nil- will execute
elseblock if there are no pending messages in neitherch, norch2 m == nilifchwas closedm2 = nilifch2was closed- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended
i, m = Channel.non_blocking_select(ch.receive_select_action?, ch2.receive_select_action?)i : Int32,m : T | T2 | Nil | NotReadym == NotReadyif there are no pending messages in neitherch, norch2m == nilif channel was closed (i == 0forch,i == 1forch2)- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended
Given ch : Channel(T), ch2 : Channel(T2), t : T, t2 : T2:
ch.send tselect
when ch.send(t)
endi, m = Channel.select(ch.send_select_action(t))i : Int32,m : Nil- will suspend current fiber if there are no receivers for
ch - if
chwas closed, or is closed while fiber is suspended, it will raiseClosedError - on
ch.receive,i == 0,m == nil, will execute the firstwhenblock
select
when ch.send(t)
else
endi, m = Channel.non_blocking_select(ch.send_select_action(t))i : Int32,m : Nil | NotReady- if
chwas closed, it will raiseClosedError- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended
- if there is a receiver on
ch,i == 0,m == nil, will execute the firstwhenblock - if there are no receivers on
ch,m == NotReady, will execute theelseblock
select
when ch.send(t)
when ch2.send(t2)
endi, m = Channel.select(ch.send_select_action(t), ch2.send_select_action(t2))i : Int32,m : Nil- will suspend current fiber if there are no receivers for
chandch2 - if
chorch2were closed, or some is closed while fiber is suspended, it will raiseClosedError - on
ch.receive,i == 0,m == nil, will execute the firstwhenblock - on
ch2.receive,i == 1,m == nil, will execute the firstwhenblock
select
when ch.send(t)
when ch2.send(t2)
else
endi, m = Channel.non_blocking_select(ch.send_select_action(t), ch2.send_select_action(t2))i : Int32,m : Nil | NotReady- if
chorch2were closed, it will raiseClosedError- Since it is a non-blocking version, there is no need need to consider if the channel is closed while fiber is suspended
- if there is a receiver on
ch,i == 0,m == nil, will execute the firstwhenblock - if there is a receiver on
ch2,i == 1,m == nil, will execute the secondwhenblock - if there are no receivers on
chandch2,m == NotReady, will execute theelseblock