semaphore.mx raw

   1  package task
   2  
   3  // Barebones semaphore implementation.
   4  // The main limitation is that if there are multiple waiters, a single Post()
   5  // call won't do anything. Only when Post() has been called to awaken all
   6  // waiters will the waiters proceed.
   7  // This limitation is not a problem when there will only be a single waiter.
   8  type Semaphore struct {
   9  	futex Futex
  10  }
  11  
  12  // Post (unlock) the semaphore, incrementing the value in the semaphore.
  13  func (s *Semaphore) Post() {
  14  	newValue := s.futex.Add(1)
  15  	if newValue == 0 {
  16  		s.futex.WakeAll()
  17  	}
  18  }
  19  
  20  // Wait (lock) the semaphore, decrementing the value in the semaphore.
  21  func (s *Semaphore) Wait() {
  22  	delta := int32(-1)
  23  	value := s.futex.Add(uint32(delta))
  24  	for {
  25  		if int32(value) >= 0 {
  26  			// Semaphore unlocked!
  27  			return
  28  		}
  29  		s.futex.Wait(value)
  30  		value = s.futex.Load()
  31  	}
  32  }
  33