@@ -2,22 +2,34 @@ package common
22
33import "sync/atomic"
44
5+ // In Go, unbounded channel means something different than what it means in Rust.
6+ // I.e. unlike Rust, "unbounded" in Go means that the channel has **no buffer**,
7+ // meaning that each attempt to send will block the channel until the receiver
8+ // reads it. Majority of primitives here in `waterfall` are designed under assumption
9+ // that sending is not blocking.
10+ const UnboundedChannelSize = 128
11+
512// Creates a new channel, returns two counterparts of it where one can only send and another can only receive.
613// Unlike traditional Go channels, these allow the receiver to mark the channel as closed which would then fail
714// to send any messages to the channel over `Send“.
815func NewChannel [M any ]() (Sender [M ], Receiver [M ]) {
9- channel := make (chan M , 128 )
16+ channel := make (chan M , UnboundedChannelSize )
1017 closed := & atomic.Bool {}
1118 sender := Sender [M ]{channel , closed }
1219 receiver := Receiver [M ]{channel , closed }
1320 return sender , receiver
1421}
1522
23+ // Sender counterpart of the channel.
1624type Sender [M any ] struct {
17- channel chan <- M
25+ // The channel itself.
26+ channel chan <- M
27+ // Atomic variable that indicates whether the channel is closed.
1828 receiverClosed * atomic.Bool
1929}
2030
31+ // Tries to send a message if the channel is not closed.
32+ // Returns the message back if the channel is closed.
2133func (s * Sender [M ]) Send (message M ) * M {
2234 if ! s .receiverClosed .Load () {
2335 s .channel <- message
@@ -27,11 +39,32 @@ func (s *Sender[M]) Send(message M) *M {
2739 }
2840}
2941
42+ // The receiver counterpart of the channel.
3043type Receiver [M any ] struct {
31- Channel <- chan M
44+ // The channel itself. It's public, so that we can combine it in `select` statements.
45+ Channel <- chan M
46+ // Atomic variable that indicates whether the channel is closed.
3247 receiverClosed * atomic.Bool
3348}
3449
35- func (r * Receiver [M ]) Close () {
50+ // Marks the channel as closed, which means that no messages could be sent via this channel.
51+ // Any attempt to send a message would result in an error. This is similar to closing the
52+ // channel except that we don't close the underlying channel (since in Go receivers can't
53+ // close the channel).
54+ //
55+ // This function reads (in a non-blocking way) all pending messages until blocking. Otherwise,
56+ // they will stay forver in a channel and get lost.
57+ func (r * Receiver [M ]) Close () []M {
3658 r .receiverClosed .Store (true )
59+
60+ messages := make ([]M , 0 )
61+ for {
62+ msg , ok := <- r .Channel
63+ if ! ok {
64+ break
65+ }
66+ messages = append (messages , msg )
67+ }
68+
69+ return messages
3770}
0 commit comments