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