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.receive
select
when m = ch.receive
end
i, m = Channel.select(ch.receive_select_action)
i : Int32
,m : T
- will suspend current fiber if there are no pending messages in
ch
- if
ch
was 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
end
m : T
- will execute
else
block 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 firstwhen
block.
i, m = Channel.non_blocking_select(ch.receive_select_action)
i : Int32
,m : T | NotReady
i == 1 && m == NotReady
if there are no pending messages inch
- if any
ch
was 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
end
m : T
,m2 : T2
- if non of the channel has messages, the current fiber will be suspended.
- if any
ch
orch2
was or is closed, the select will raiseClosedError
- on
ch.send(t)
,m == t
, execute firstwhen
block. - on
ch2.send(t)
,m2 == t
, execute secondwhen
block.
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
ch
norch2
- if any
ch
orch2
was closed, or is closed while fiber is suspended, it will raiseClosedError
select
when m1 = ch.receive
when m2 = ch2.receive
else
end
m : T
,m2 : T2
- if any
ch
orch2
was 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
else
block will execute.
m = ch.receive?
select
when m = ch.receive?
end
i, 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?
end
m1 : T1 | Nil
,m2 : T2 | Nil
- will suspend current fiber if there are no pending messages in neither
ch
norch2
- 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
ch
norch2
- 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
end
i, m = Channel.non_blocking_select(ch.receive_select_action?)
i : Int32
,m : T | Nil | NotReady
m == NotReady
if there are no pending messages inch
m == nil
if 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
end
m : T | Nil
,m2 : T2 | Nil
- will execute
else
block if there are no pending messages in neitherch
, norch2
m == nil
ifch
was closedm2 = nil
ifch2
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
i, m = Channel.non_blocking_select(ch.receive_select_action?, ch2.receive_select_action?)
i : Int32
,m : T | T2 | Nil | NotReady
m == NotReady
if there are no pending messages in neitherch
, norch2
m == nil
if channel was closed (i == 0
forch
,i == 1
forch2
)- 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 t
select
when ch.send(t)
end
i, m = Channel.select(ch.send_select_action(t))
i : Int32
,m : Nil
- will suspend current fiber if there are no receivers for
ch
- if
ch
was closed, or is closed while fiber is suspended, it will raiseClosedError
- on
ch.receive
,i == 0
,m == nil
, will execute the firstwhen
block
select
when ch.send(t)
else
end
i, m = Channel.non_blocking_select(ch.send_select_action(t))
i : Int32
,m : Nil | NotReady
- if
ch
was 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 firstwhen
block - if there are no receivers on
ch
,m == NotReady
, will execute theelse
block
select
when ch.send(t)
when ch2.send(t2)
end
i, 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
ch
andch2
- if
ch
orch2
were closed, or some is closed while fiber is suspended, it will raiseClosedError
- on
ch.receive
,i == 0
,m == nil
, will execute the firstwhen
block - on
ch2.receive
,i == 1
,m == nil
, will execute the firstwhen
block
select
when ch.send(t)
when ch2.send(t2)
else
end
i, m = Channel.non_blocking_select(ch.send_select_action(t), ch2.send_select_action(t2))
i : Int32
,m : Nil | NotReady
- if
ch
orch2
were 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 firstwhen
block - if there is a receiver on
ch2
,i == 1
,m == nil
, will execute the secondwhen
block - if there are no receivers on
ch
andch2
,m == NotReady
, will execute theelse
block