@@ -19,6 +19,7 @@ package batcher
1919import (
2020 "errors"
2121 "sync"
22+ "sync/atomic"
2223 "time"
2324)
2425
@@ -59,6 +60,7 @@ type basicBatcher struct {
5960 lock sync.RWMutex
6061 batchChan chan []interface {}
6162 availableBytes uint
63+ waiting int32
6264}
6365
6466// New creates a new Batcher using the provided arguments.
@@ -85,6 +87,7 @@ func New(maxTime time.Duration, maxItems, maxBytes, queueLen uint, calculate Cal
8587
8688// Put adds items to the batcher. If Put is continually called without calls to
8789// Get, an unbounded number of go-routines will be generated.
90+ // Note: there is no order guarantee for items entering/leaving the batcher.
8891func (b * basicBatcher ) Put (item interface {}) error {
8992 b .lock .Lock ()
9093 if b .disposed {
@@ -108,6 +111,7 @@ func (b *basicBatcher) Put(item interface{}) error {
108111// one of the conditions for a "complete" batch is reached. If Put is
109112// continually called without calls to Get, an unbounded number of
110113// go-routines will be generated.
114+ // Note: there is no order guarantee for items entering/leaving the batcher.
111115func (b * basicBatcher ) Get () ([]interface {}, error ) {
112116 // Don't check disposed yet so any items remaining in the queue
113117 // will be returned properly.
@@ -163,15 +167,9 @@ func (b *basicBatcher) Dispose() {
163167 b .items = nil
164168
165169 // Drain the batch channel and all routines waiting to put on the channel
166- DrainLoop:
167- for {
168- select {
169- case <- b .batchChan :
170- case <- time .After (5 * time .Millisecond ):
171- break DrainLoop
172- }
170+ for atomic .LoadInt32 (& b .waiting ) > 0 {
171+ <- b .batchChan
173172 }
174-
175173 close (b .batchChan )
176174 b .lock .Unlock ()
177175}
@@ -193,7 +191,13 @@ func (b *basicBatcher) flush() {
193191 for i , val := range b .items {
194192 cpItems [i ] = val
195193 }
196- go func () { b .batchChan <- cpItems }()
194+ // Signal one more waiter for the batch channel
195+ atomic .AddInt32 (& b .waiting , 1 )
196+ // Don't block on the channel put
197+ go func () {
198+ b .batchChan <- cpItems
199+ atomic .AddInt32 (& b .waiting , - 1 )
200+ }()
197201 b .items = make ([]interface {}, 0 , b .maxItems )
198202 b .availableBytes = 0
199203}
0 commit comments