Skip to content

Commit 29b6ff2

Browse files
committed
add comment and modify test
1 parent 529f392 commit 29b6ff2

File tree

2 files changed

+18
-27
lines changed

2 files changed

+18
-27
lines changed

semaphore/semaphore.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func (s *Weighted) Acquire(ctx context.Context, n int64) error {
6969
default:
7070
isFront := s.waiters.Front() == elem
7171
s.waiters.Remove(elem)
72+
// If we're at the front and there're extra tokens left, notify other waiters.
7273
if isFront && s.size > s.cur {
7374
s.notifyWaiters()
7475
}

semaphore/semaphore_test.go

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -174,39 +174,29 @@ func TestLargeAcquireDoesntStarve(t *testing.T) {
174174
func TestAllocCancelDoesntStarve(t *testing.T) {
175175
sem := semaphore.NewWeighted(10)
176176

177-
// hold 1 read lock
177+
// Block off a portion of the semaphore so that Acquire(_, 10) can eventually succeed.
178178
sem.Acquire(context.Background(), 1)
179179

180+
// In the background, Acquire(_, 10).
181+
ctx, cancel := context.WithCancel(context.Background())
182+
defer cancel()
180183
go func() {
181-
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Millisecond*300)
182-
defer cancelFunc()
183-
// start a write lock request that will giveup after 300ms
184-
err := sem.Acquire(ctx, 10)
185-
if err == nil {
186-
t.FailNow()
187-
}
184+
sem.Acquire(ctx, 10)
188185
}()
189186

190-
// sleep 100ms, long enough for the Lock request to be queued
191-
time.Sleep(time.Millisecond * 100)
192-
193-
// this channel will be closed if the following RLock succeeded
194-
doneCh := make(chan struct{})
195-
go func() {
196-
// try to grab a read lock, it will be queued after the Lock request
197-
// but should be notified when the Lock request is canceled
198-
err := sem.Acquire(context.Background(), 1)
199-
if err != nil {
200-
t.FailNow()
201-
}
187+
// Wait until the Acquire(_, 10) call blocks.
188+
for sem.TryAcquire(1) {
202189
sem.Release(1)
203-
close(doneCh)
204-
}()
190+
runtime.Gosched()
191+
}
192+
193+
// Now try to grab a read lock, and simultaneously unblock the Acquire(_, 10) call.
194+
// Both Acquire calls should unblock and return, in either order.
195+
go cancel()
205196

206-
// doneCh should be closed if the above RLock succeeded
207-
select {
208-
case <-doneCh:
209-
case <-time.After(time.Second):
210-
t.FailNow()
197+
err := sem.Acquire(context.Background(), 1)
198+
if err != nil {
199+
t.Fatalf("Acquire(_, 1) failed unexpectedly: %v", err)
211200
}
201+
sem.Release(1)
212202
}

0 commit comments

Comments
 (0)