Found by the race detector and existing tests.
To avoid introducing a lock into this hot path,
calculate and cache whether any peers exist.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
}
peers struct {
- sync.RWMutex
- keyMap map[NoisePublicKey]*Peer
+ empty AtomicBool // empty reports whether len(keyMap) == 0
+ sync.RWMutex // protects keyMap
+ keyMap map[NoisePublicKey]*Peer
}
// unprotected / "self-synchronising resources"
// remove from peer map
delete(device.peers.keyMap, key)
+ device.peers.empty.Set(len(device.peers.keyMap) == 0)
}
func deviceUpdateState(device *Device) {
// add
device.peers.keyMap[pk] = peer
+ device.peers.empty.Set(false)
// start peer
}
func (peer *Peer) timersActive() bool {
- return peer.isRunning.Get() && peer.device != nil && peer.device.isUp.Get() && len(peer.device.peers.keyMap) > 0
+ return peer.isRunning.Get() && peer.device != nil && peer.device.isUp.Get() && !peer.device.peers.empty.Get()
}
func expiredRetransmitHandshake(peer *Peer) {