From 7166d151aa33ee6f98ec05005f67e3954755379b Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 3 Apr 2015 18:12:03 +0100 Subject: [PATCH] make route calculcation more efficient and properly async Instead of following the usual actor pattern, we use a 1-place channel with a non-blocking send. Essentially, if there is already a pending recalculation request queued up, there is no point enqueuing another one. --- router/gossip_test.go | 2 +- router/routes.go | 39 +++++++++++++++++---------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/router/gossip_test.go b/router/gossip_test.go index 0146eef6..00b87228 100644 --- a/router/gossip_test.go +++ b/router/gossip_test.go @@ -21,7 +21,7 @@ type mockChannelConnection struct { func NewTestRouter(name PeerName) *Router { router := NewRouter(nil, name, "", nil, 10, 1024, nil) router.ConnectionMaker.actionChan = make(chan ConnectionMakerAction, ChannelSize) - router.Routes.actionChan = make(chan RoutesAction, ChannelSize) + router.Routes.recalculate = make(chan *struct{}, 1) return router } diff --git a/router/routes.go b/router/routes.go index 22a59ce1..85669315 100644 --- a/router/routes.go +++ b/router/routes.go @@ -8,11 +8,11 @@ import ( type Routes struct { sync.RWMutex - ourself *Peer - peers *Peers - unicast map[PeerName]PeerName - broadcast map[PeerName][]PeerName - actionChan chan<- RoutesAction + ourself *Peer + peers *Peers + unicast map[PeerName]PeerName + broadcast map[PeerName][]PeerName + recalculate chan<- *struct{} } func NewRoutes(ourself *Peer, peers *Peers) *Routes { @@ -27,9 +27,9 @@ func NewRoutes(ourself *Peer, peers *Peers) *Routes { } func (routes *Routes) Start() { - actionChan := make(chan RoutesAction, ChannelSize) - routes.actionChan = actionChan - go routes.actorLoop(actionChan) + recalculate := make(chan *struct{}, 1) + routes.recalculate = recalculate + go routes.run(recalculate) } func (routes *Routes) Unicast(name PeerName) (PeerName, bool) { @@ -64,13 +64,16 @@ func (routes *Routes) String() string { return buf.String() } -// ACTOR client API - -type RoutesAction func() - -// Async. func (routes *Routes) Recalculate() { - routes.actionChan <- func() { + select { + case routes.recalculate <- nil: + default: + } +} + +func (routes *Routes) run(recalculate <-chan *struct{}) { + for { + <-recalculate unicast := routes.calculateUnicast() broadcast := routes.calculateBroadcast() routes.Lock() @@ -80,14 +83,6 @@ func (routes *Routes) Recalculate() { } } -// ACTOR server - -func (routes *Routes) actorLoop(actionChan <-chan RoutesAction) { - for { - (<-actionChan)() - } -} - // Calculate all the routes for the question: if *we* want to send a // packet to Peer X, what is the next hop? //