commit
						caa175c710
					
				|  | @ -38,11 +38,7 @@ func (r *regulator) enter() { | |||
| 
 | ||||
| func (r *regulator) exit() { | ||||
| 	r.L.Lock() | ||||
| 	// We only need to signal to a waiting FS operation if we're already at the
 | ||||
| 	// limit of threads used
 | ||||
| 	if r.available == 0 { | ||||
| 		r.Signal() | ||||
| 	} | ||||
| 	r.Signal() | ||||
| 	r.available++ | ||||
| 	r.L.Unlock() | ||||
| } | ||||
|  |  | |||
|  | @ -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