- get rid of individual Peer locks
- hold Peers read (or write) lock and LocalPeer read lock while
performing route calculations
This eliminates the deadlock resulting from the inconsistent lock
acquisition order in route calculcation.
Fixes#643.
...by obtaining our connection set just once. This also guards against
potential locking issues, since we no longer obtain the required
lock on our local peer while holding a lock on Peers.
Note that this change means the connection list can be out of date by
the time we enter Peers.ForEach. However, previously it was possible
for the list to change for each peer we are iterating over. So it's
just a different flavour of out-of-dateness.
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.
d5eb76f32 replaced (*Peer)ForEachConnection into (*Peer)Connections(),
and consequently converted some nested functions into for loops. But
the "return" statements in those nested functions were left as-was,
and so exited the outer function rather than moving on to the next
iteration.
Fixes#497