| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package alloclim
- import "sync"
- // Manages reservations sharing a common allocation limit.
- type Limiter struct {
- // Maximum outstanding allocation space.
- Max int64
- initOnce sync.Once
- mu sync.Mutex
- // Current unallocated space.
- value int64
- // Reservations waiting to in the order they arrived.
- waiting []*Reservation
- }
- func (me *Limiter) initValue() {
- me.value = me.Max
- }
- func (me *Limiter) init() {
- me.initOnce.Do(func() {
- me.initValue()
- })
- }
- func (me *Limiter) Reserve(n int64) *Reservation {
- r := &Reservation{
- l: me,
- n: n,
- }
- me.init()
- me.mu.Lock()
- if n <= me.value {
- me.value -= n
- r.granted.Set()
- } else {
- me.waiting = append(me.waiting, r)
- }
- me.mu.Unlock()
- return r
- }
- func (me *Limiter) doWakesLocked() {
- for {
- if len(me.waiting) == 0 {
- break
- }
- r := me.waiting[0]
- switch {
- case r.cancelled.IsSet():
- case r.n <= me.value:
- if r.wake() {
- me.value -= r.n
- }
- default:
- return
- }
- me.waiting = me.waiting[1:]
- }
- }
- func (me *Limiter) doWakes() {
- me.mu.Lock()
- me.doWakesLocked()
- me.mu.Unlock()
- }
- func (me *Limiter) addValue(n int64) {
- me.mu.Lock()
- me.value += n
- me.doWakesLocked()
- me.mu.Unlock()
- }
- func (me *Limiter) Value() int64 {
- me.mu.Lock()
- defer me.mu.Unlock()
- return me.value
- }
|