github.com/Cloud-Foundations/Dominator@v0.3.4/lib/concurrent/incrementer.go (about) 1 package concurrent 2 3 import "sync" 4 5 type incrementer struct { 6 state *State 7 mutex sync.Mutex // Protect the following fields. 8 completionCount uint 9 currentConcurrency uint 10 } 11 12 func newStateWithLinearConcurrencyIncrease(initialNumConcurrent uint, 13 maximumNumConcurrent uint) *State { 14 if initialNumConcurrent < 1 { 15 panic("initialNumConcurrent must not be zero") 16 } 17 p := &incrementer{currentConcurrency: initialNumConcurrent} 18 state := newState(maximumNumConcurrent, p) 19 p.state = state 20 if initialNumConcurrent > uint(cap(state.semaphore)) { 21 panic("initialNumConcurrent must not exceed concurrency") 22 } 23 numToBlock := uint(cap(state.semaphore)) - initialNumConcurrent 24 for count := uint(0); count < numToBlock; count++ { 25 state.semaphore <- struct{}{} 26 } 27 return state 28 } 29 30 // This is called from a goroutine. 31 func (p *incrementer) put() { 32 p.mutex.Lock() 33 defer p.mutex.Unlock() 34 if p.currentConcurrency >= uint(cap(p.state.semaphore)) { 35 return 36 } 37 p.completionCount++ 38 if p.completionCount < p.currentConcurrency { 39 return 40 } 41 p.completionCount = 0 42 p.currentConcurrency++ 43 select { 44 case <-p.state.semaphore: 45 default: 46 panic("no concurrency limits to remove") 47 } 48 }