github.com/aclements/go-misc@v0.0.0-20240129233631-2f6ede80790c/go-weave/weave/sema.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package weave 6 7 // Semaphore is a FIFO counted semaphore. 8 type Semaphore struct { 9 avail int 10 wait *semwait 11 waitEnd *semwait 12 } 13 14 type semwait struct { 15 n int 16 thr *thread 17 next *semwait 18 } 19 20 func (s *Semaphore) Acquire(n int) { 21 if s.avail >= n { 22 s.avail -= n 23 return 24 } 25 this := globalSched.curThread 26 w := &semwait{n, this, nil} 27 if s.waitEnd != nil { 28 s.waitEnd.next = w 29 } else { 30 s.wait = w 31 } 32 s.waitEnd = w 33 this.block(s.reset) 34 } 35 36 func (s *Semaphore) Release(n int) { 37 s.avail += n 38 any := false 39 for s.wait != nil && s.avail >= s.wait.n { 40 any = true 41 w := s.wait 42 s.wait = w.next 43 if s.wait == nil { 44 s.waitEnd = nil 45 } 46 s.avail -= w.n 47 w.thr.unblock() 48 } 49 if any { 50 globalSched.Sched() 51 } 52 } 53 54 func (s *Semaphore) reset() { 55 *s = Semaphore{} 56 }