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  }