mirror of
https://github.com/distribution/distribution
synced 2024-11-06 19:35:52 +01:00
Merge pull request #2299 from dmage/regulator
Fix signalling Wait in regulator.enter
This commit is contained in:
commit
caa175c710
@ -38,11 +38,7 @@ func (r *regulator) enter() {
|
|||||||
|
|
||||||
func (r *regulator) exit() {
|
func (r *regulator) exit() {
|
||||||
r.L.Lock()
|
r.L.Lock()
|
||||||
// We only need to signal to a waiting FS operation if we're already at the
|
r.Signal()
|
||||||
// limit of threads used
|
|
||||||
if r.available == 0 {
|
|
||||||
r.Signal()
|
|
||||||
}
|
|
||||||
r.available++
|
r.available++
|
||||||
r.L.Unlock()
|
r.L.Unlock()
|
||||||
}
|
}
|
||||||
|
67
registry/storage/driver/base/regulator_test.go
Normal file
67
registry/storage/driver/base/regulator_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package base
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRegulatorEnterExit(t *testing.T) {
|
||||||
|
const limit = 500
|
||||||
|
|
||||||
|
r := NewRegulator(nil, limit).(*regulator)
|
||||||
|
|
||||||
|
for try := 0; try < 50; try++ {
|
||||||
|
run := make(chan struct{})
|
||||||
|
|
||||||
|
var firstGroupReady sync.WaitGroup
|
||||||
|
var firstGroupDone sync.WaitGroup
|
||||||
|
firstGroupReady.Add(limit)
|
||||||
|
firstGroupDone.Add(limit)
|
||||||
|
for i := 0; i < limit; i++ {
|
||||||
|
go func() {
|
||||||
|
r.enter()
|
||||||
|
firstGroupReady.Done()
|
||||||
|
<-run
|
||||||
|
r.exit()
|
||||||
|
firstGroupDone.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
firstGroupReady.Wait()
|
||||||
|
|
||||||
|
// now we exhausted all the limit, let's run a little bit more
|
||||||
|
var secondGroupReady sync.WaitGroup
|
||||||
|
var secondGroupDone sync.WaitGroup
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
secondGroupReady.Add(1)
|
||||||
|
secondGroupDone.Add(1)
|
||||||
|
go func() {
|
||||||
|
secondGroupReady.Done()
|
||||||
|
r.enter()
|
||||||
|
r.exit()
|
||||||
|
secondGroupDone.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
secondGroupReady.Wait()
|
||||||
|
|
||||||
|
// allow the first group to return resources
|
||||||
|
close(run)
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
secondGroupDone.Wait()
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Fatal("some r.enter() are still locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
firstGroupDone.Wait()
|
||||||
|
|
||||||
|
if r.available != limit {
|
||||||
|
t.Fatalf("r.available: got %d, want %d", r.available, limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user