mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
common/mclock: use ping channel instead of GoSched
This commit is contained in:
parent
901f68d0c5
commit
7aa34bc11b
3 changed files with 31 additions and 6 deletions
|
|
@ -33,15 +33,24 @@ func Now() AbsTime {
|
||||||
|
|
||||||
// Clock interface makes it possible to replace the monotonic system clock with
|
// Clock interface makes it possible to replace the monotonic system clock with
|
||||||
// a simulated clock
|
// a simulated clock
|
||||||
|
//
|
||||||
|
// Note: event loops capable of running with a simulated clock should listen to PingChannel.
|
||||||
|
// MonotonicClock also implements this function to ensure interface compatibility.
|
||||||
type Clock interface {
|
type Clock interface {
|
||||||
Now() AbsTime
|
Now() AbsTime
|
||||||
Sleep(time.Duration)
|
Sleep(time.Duration)
|
||||||
After(time.Duration) <-chan time.Time
|
After(time.Duration) <-chan time.Time
|
||||||
|
PingChannel() chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonotonicClock implements Clock using the system clock
|
// MonotonicClock implements Clock using the system clock
|
||||||
type MonotonicClock struct{}
|
type MonotonicClock struct{}
|
||||||
|
|
||||||
|
// PingChannel implements Clock by returning a dummy nil channel
|
||||||
|
func (MonotonicClock) PingChannel() chan struct{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Now implements Clock
|
// Now implements Clock
|
||||||
func (MonotonicClock) Now() AbsTime {
|
func (MonotonicClock) Now() AbsTime {
|
||||||
return AbsTime(monotime.Now())
|
return AbsTime(monotime.Now())
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
package mclock
|
package mclock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -39,18 +38,23 @@ type SimulatedClock struct {
|
||||||
now AbsTime
|
now AbsTime
|
||||||
scheduled []event
|
scheduled []event
|
||||||
stop bool
|
stop bool
|
||||||
|
pingCh chan struct{}
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSimulatedClock creates a new simulated clock
|
// NewSimulatedClock creates a new simulated clock
|
||||||
func NewSimulatedClock(maxStep time.Duration, goSchedCount int) *SimulatedClock {
|
func NewSimulatedClock(maxStep time.Duration, pingCount int) *SimulatedClock {
|
||||||
s := &SimulatedClock{scheduled: make([]event, 0, 100)}
|
s := &SimulatedClock{scheduled: make([]event, 0, 100), pingCh: make(chan struct{})}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
lastScheduled := 0
|
lastScheduled := 0
|
||||||
for {
|
for {
|
||||||
for i := 0; i < goSchedCount; i++ {
|
timeout := time.After(maxStep / 100)
|
||||||
runtime.Gosched()
|
for i := 0; i < pingCount; i++ {
|
||||||
|
select {
|
||||||
|
case s.pingCh <- struct{}{}:
|
||||||
|
case <-timeout:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
if s.stop {
|
if s.stop {
|
||||||
|
|
@ -76,6 +80,11 @@ func NewSimulatedClock(maxStep time.Duration, goSchedCount int) *SimulatedClock
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PingChannel returns a channel that event loops should listen to
|
||||||
|
func (s *SimulatedClock) PingChannel() chan struct{} {
|
||||||
|
return s.pingCh
|
||||||
|
}
|
||||||
|
|
||||||
// Stop stops the clock (Sleeps and Afters will never return after this)
|
// Stop stops the clock (Sleeps and Afters will never return after this)
|
||||||
func (s *SimulatedClock) Stop() {
|
func (s *SimulatedClock) Stop() {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
|
|
@ -97,7 +106,13 @@ func (s *SimulatedClock) Sleep(d time.Duration) {
|
||||||
s.insert(d, func() {
|
s.insert(d, func() {
|
||||||
close(done)
|
close(done)
|
||||||
})
|
})
|
||||||
<-done
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
case <-s.pingCh:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After implements Clock
|
// After implements Clock
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
case <-clock.PingChannel():
|
||||||
case <-tickCh:
|
case <-tickCh:
|
||||||
i := rand.Intn(clientCount)
|
i := rand.Intn(clientCount)
|
||||||
if connected[i] {
|
if connected[i] {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue