github.com/thanos-io/thanos@v0.32.5/pkg/cacheutil/async_op.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package cacheutil 5 6 import ( 7 "sync" 8 9 "github.com/pkg/errors" 10 ) 11 12 type asyncOperationProcessor struct { 13 // Channel used to notify internal goroutines when they should quit. 14 stop chan struct{} 15 16 // Channel used to enqueue async operations. 17 asyncQueue chan func() 18 19 // Wait group used to wait all workers on stopping. 20 workers sync.WaitGroup 21 } 22 23 func newAsyncOperationProcessor(bufferSize, concurrency int) *asyncOperationProcessor { 24 p := &asyncOperationProcessor{ 25 stop: make(chan struct{}, 1), 26 asyncQueue: make(chan func(), bufferSize), 27 } 28 29 p.workers.Add(concurrency) 30 for i := 0; i < concurrency; i++ { 31 go p.asyncQueueProcessLoop() 32 } 33 34 return p 35 } 36 37 func (p *asyncOperationProcessor) Stop() { 38 close(p.stop) 39 40 // Wait until all workers have terminated. 41 p.workers.Wait() 42 } 43 44 func (p *asyncOperationProcessor) asyncQueueProcessLoop() { 45 defer p.workers.Done() 46 47 for { 48 select { 49 case op := <-p.asyncQueue: 50 op() 51 case <-p.stop: 52 return 53 } 54 } 55 } 56 57 var errAsyncBufferFull = errors.New("the async buffer is full") 58 59 func (p *asyncOperationProcessor) enqueueAsync(op func()) error { 60 select { 61 case p.asyncQueue <- op: 62 return nil 63 default: 64 return errAsyncBufferFull 65 } 66 }