@@ -174,39 +174,29 @@ func TestLargeAcquireDoesntStarve(t *testing.T) {
174174func TestAllocCancelDoesntStarve (t * testing.T ) {
175175sem := semaphore .NewWeighted (10 )
176176
177- // hold 1 read lock
177+ // Block off a portion of the semaphore so that Acquire(_, 10) can eventually succeed.
178178sem .Acquire (context .Background (), 1 )
179179
180+ // In the background, Acquire(_, 10).
181+ ctx , cancel := context .WithCancel (context .Background ())
182+ defer cancel ()
180183go 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 ) {
202189sem .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