@@ -58,14 +58,18 @@ func (cq *ConcurrentQueue) start() {
58
58
go func () {
59
59
defer cq .wg .Done ()
60
60
61
+ readLoop:
61
62
for {
62
63
nextElement := cq .overflow .Front ()
63
64
if nextElement == nil {
64
65
// Overflow queue is empty so incoming items can be pushed
65
66
// directly to the output channel. If output channel is full
66
67
// though, push to overflow.
67
68
select {
68
- case item := <- cq .chanIn :
69
+ case item , ok := <- cq .chanIn :
70
+ if ! ok {
71
+ break readLoop
72
+ }
69
73
select {
70
74
case cq .chanOut <- item :
71
75
// Optimistically push directly to chanOut
@@ -79,7 +83,10 @@ func (cq *ConcurrentQueue) start() {
79
83
// Overflow queue is not empty, so any new items get pushed to
80
84
// the back to preserve order.
81
85
select {
82
- case item := <- cq .chanIn :
86
+ case item , ok := <- cq .chanIn :
87
+ if ! ok {
88
+ break readLoop
89
+ }
83
90
cq .overflow .PushBack (item )
84
91
case cq .chanOut <- nextElement .Value :
85
92
cq .overflow .Remove (nextElement )
@@ -88,6 +95,22 @@ func (cq *ConcurrentQueue) start() {
88
95
}
89
96
}
90
97
}
98
+
99
+ // Incoming channel has been closed. Empty overflow queue into
100
+ // the outgoing channel.
101
+ nextElement := cq .overflow .Front ()
102
+ for nextElement != nil {
103
+ select {
104
+ case cq .chanOut <- nextElement .Value :
105
+ cq .overflow .Remove (nextElement )
106
+ case <- cq .quit :
107
+ return
108
+ }
109
+ nextElement = cq .overflow .Front ()
110
+ }
111
+
112
+ // Close outgoing channel.
113
+ close (cq .chanOut )
91
114
}()
92
115
}
93
116
0 commit comments