From 74b3f8d44e1ab9b06ab4725697b02a657f6e68b8 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 6 Apr 2015 11:35:11 +0100 Subject: [PATCH] use map[...]struct{} for sets instead of map[...]bool See https://groups.google.com/d/msg/golang-nuts/lb4xLHq7wug/MhrSLkyS4F8J We don't really care about the performance aspect of this, but using struct{}{} values is in some way canonical since it means the representation carries no redundant information. --- router/connection_maker.go | 34 +++++++++++++++++++--------------- router/mocks_test.go | 4 ++-- router/peers.go | 2 +- router/router.go | 6 +++--- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/router/connection_maker.go b/router/connection_maker.go index 67a002d2..8f2045b1 100644 --- a/router/connection_maker.go +++ b/router/connection_maker.go @@ -18,7 +18,7 @@ type ConnectionMaker struct { ourself *LocalPeer peers *Peers targets map[string]*Target - cmdLineAddress map[string]bool + cmdLineAddress map[string]struct{} actionChan chan<- ConnectionMakerAction } @@ -35,7 +35,7 @@ func NewConnectionMaker(ourself *LocalPeer, peers *Peers) *ConnectionMaker { return &ConnectionMaker{ ourself: ourself, peers: peers, - cmdLineAddress: make(map[string]bool), + cmdLineAddress: make(map[string]struct{}), targets: make(map[string]*Target)} } @@ -47,7 +47,7 @@ func (cm *ConnectionMaker) Start() { func (cm *ConnectionMaker) InitiateConnection(address string) { cm.actionChan <- func() bool { - cm.cmdLineAddress[NormalisePeerAddr(address)] = true + cm.cmdLineAddress[NormalisePeerAddr(address)] = struct{}{} if target, found := cm.targets[address]; found { target.tryAfter, target.tryInterval = tryImmediately() } @@ -111,19 +111,19 @@ func (cm *ConnectionMaker) queryLoop(actionChan <-chan ConnectionMakerAction) { } func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration { - validTarget := make(map[string]bool) + validTarget := make(map[string]struct{}) // copy the set of things we are connected to, so we can access them without locking - ourConnectedPeers := make(map[PeerName]bool) - ourConnectedTargets := make(map[string]bool) + ourConnectedPeers := make(map[PeerName]struct{}) + ourConnectedTargets := make(map[string]struct{}) for _, conn := range cm.ourself.Connections() { - ourConnectedPeers[conn.Remote().Name] = true - ourConnectedTargets[conn.RemoteTCPAddr()] = true + ourConnectedPeers[conn.Remote().Name] = struct{}{} + ourConnectedTargets[conn.RemoteTCPAddr()] = struct{}{} } addTarget := func(address string) { - if !ourConnectedTargets[address] { - validTarget[address] = true + if _, connected := ourConnectedTargets[address]; !connected { + validTarget[address] = struct{}{} cm.addTarget(address) } } @@ -138,7 +138,10 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration { cm.peers.ForEach(func(peer *Peer) { for _, conn := range peer.Connections() { otherPeer := conn.Remote().Name - if otherPeer == cm.ourself.Name || ourConnectedPeers[otherPeer] { + if otherPeer == cm.ourself.Name { + continue + } + if _, connected := ourConnectedPeers[otherPeer]; connected { continue } address := conn.RemoteTCPAddr() @@ -163,25 +166,26 @@ func (cm *ConnectionMaker) addTarget(address string) { } } -func (cm *ConnectionMaker) connectToTargets(validTarget map[string]bool, ourConnectedTargets map[string]bool) time.Duration { +func (cm *ConnectionMaker) connectToTargets(validTarget map[string]struct{}, ourConnectedTargets map[string]struct{}) time.Duration { now := time.Now() // make sure we catch items just added after := MaxDuration for address, target := range cm.targets { - if ourConnectedTargets[address] { + if _, connected := ourConnectedTargets[address]; connected { delete(cm.targets, address) continue } if target.attempting { continue } - if !validTarget[address] { + if _, valid := validTarget[address]; !valid { delete(cm.targets, address) continue } switch duration := target.tryAfter.Sub(now); { case duration <= 0: target.attempting = true - go cm.attemptConnection(address, cm.cmdLineAddress[address]) + _, isCmdLineAddress := cm.cmdLineAddress[address] + go cm.attemptConnection(address, isCmdLineAddress) case duration < after: after = duration } diff --git a/router/mocks_test.go b/router/mocks_test.go index 3d5c9178..d71aa280 100644 --- a/router/mocks_test.go +++ b/router/mocks_test.go @@ -48,9 +48,9 @@ func newMockConnection(from, to *Peer) Connection { } func checkEqualConns(t *testing.T, ourName PeerName, got, wanted map[PeerName]Connection) { - checkConns := make(map[PeerName]bool) + checkConns := make(map[PeerName]struct{}) for _, conn := range wanted { - checkConns[conn.Remote().Name] = true + checkConns[conn.Remote().Name] = struct{}{} } for _, conn := range got { remoteName := conn.Remote().Name diff --git a/router/peers.go b/router/peers.go index 5edf5639..a0ff2cbe 100644 --- a/router/peers.go +++ b/router/peers.go @@ -169,7 +169,7 @@ func (peers *Peers) garbageCollect() []*Peer { func setFromPeersMap(peers map[PeerName]*Peer) PeerNameSet { names := make(PeerNameSet) for name := range peers { - names[name] = true + names[name] = struct{}{} } return names } diff --git a/router/router.go b/router/router.go index af245e8e..297eca08 100644 --- a/router/router.go +++ b/router/router.go @@ -350,7 +350,7 @@ func handleSpecialFrame(relayConn *LocalConnection, sender *net.UDPAddr, frame [ // Gossiper methods - the Router is the topology Gossiper -type PeerNameSet map[PeerName]bool +type PeerNameSet map[PeerName]struct{} type TopologyGossipData struct { peers *Peers @@ -360,14 +360,14 @@ type TopologyGossipData struct { func NewTopologyGossipData(peers *Peers, update ...*Peer) *TopologyGossipData { names := make(PeerNameSet) for _, p := range update { - names[p.Name] = true + names[p.Name] = struct{}{} } return &TopologyGossipData{peers: peers, update: names} } func (d *TopologyGossipData) Merge(other GossipData) { for name := range other.(*TopologyGossipData).update { - d.update[name] = true + d.update[name] = struct{}{} } }