move localRefCount accounting responsibility from Peer to Peers
This makes for a more symmetric API - Peers.FetchWithDefault does the increment and Peers.Dereference does the decrement, whereas previously the latter was done by Peer.DecrementLocalRefCount. This does increase lock granularity, i.e. modifying any ref count now requires a write lock on Peers.
This commit is contained in:
1 parent
3e6eef5ebd
commit
505ced5cc8
5 files changed
+19
-45
No files matched your search
@@ -412,7 +412,7 @@ func (conn *LocalConnection) shutdown(err error) {
|
||||
}
|
||||
|
||||
if conn.remote != nil {
|
||||
conn.remote.DecrementLocalRefCount()
|
||||
conn.Router.Peers.Dereference(conn.remote)
|
||||
conn.Router.Ourself.DeleteConnection(conn)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ func (router *Router) DeleteTestChannelConnection(r *Router) {
|
||||
fromPeer, _ := r.Peers.Fetch(fromName)
|
||||
toPeer, _ := router.Peers.Fetch(toName)
|
||||
|
||||
fromPeer.DecrementLocalRefCount()
|
||||
toPeer.DecrementLocalRefCount()
|
||||
r.Peers.Dereference(fromPeer)
|
||||
router.Peers.Dereference(toPeer)
|
||||
|
||||
conn, _ := router.Ourself.ConnectionTo(toName)
|
||||
router.Ourself.handleDeleteConnection(conn)
|
||||
|
||||
@@ -33,7 +33,7 @@ func (peers *Peers) AddTestRemoteConnection(p1, p2 *Peer) {
|
||||
func (peers *Peers) DeleteTestConnection(p *Peer) {
|
||||
toName := p.Name
|
||||
toPeer, _ := peers.Fetch(toName)
|
||||
toPeer.DecrementLocalRefCount()
|
||||
peers.Dereference(toPeer)
|
||||
conn, _ := peers.ourself.ConnectionTo(toName)
|
||||
peers.ourself.deleteConnection(conn)
|
||||
}
|
||||
|
||||
+1
-19
@@ -13,7 +13,7 @@ type Peer struct {
|
||||
NickName string
|
||||
UID uint64
|
||||
version uint64
|
||||
localRefCount uint64
|
||||
localRefCount uint64 // maintained by Peers
|
||||
connections map[PeerName]Connection
|
||||
}
|
||||
|
||||
@@ -48,24 +48,6 @@ func (peer *Peer) Version() uint64 {
|
||||
return peer.version
|
||||
}
|
||||
|
||||
func (peer *Peer) IncrementLocalRefCount() {
|
||||
peer.Lock()
|
||||
defer peer.Unlock()
|
||||
peer.localRefCount++
|
||||
}
|
||||
|
||||
func (peer *Peer) DecrementLocalRefCount() {
|
||||
peer.Lock()
|
||||
defer peer.Unlock()
|
||||
peer.localRefCount--
|
||||
}
|
||||
|
||||
func (peer *Peer) IsLocallyReferenced() bool {
|
||||
peer.RLock()
|
||||
defer peer.RUnlock()
|
||||
return peer.localRefCount != 0
|
||||
}
|
||||
|
||||
func (peer *Peer) ConnectionTo(name PeerName) (Connection, bool) {
|
||||
peer.RLock()
|
||||
defer peer.RUnlock()
|
||||
|
||||
+14
-22
@@ -47,20 +47,17 @@ func NewPeers(ourself *LocalPeer, onGC func(*Peer)) *Peers {
|
||||
}
|
||||
|
||||
func (peers *Peers) FetchWithDefault(peer *Peer) *Peer {
|
||||
peers.RLock()
|
||||
res, found := peers.fetchAlias(peer)
|
||||
peers.RUnlock()
|
||||
if found {
|
||||
return res
|
||||
}
|
||||
peers.Lock()
|
||||
defer peers.Unlock()
|
||||
res, found = peers.fetchAlias(peer)
|
||||
if found {
|
||||
return res
|
||||
if existingPeer, found := peers.table[peer.Name]; found {
|
||||
if existingPeer.UID != peer.UID {
|
||||
return nil
|
||||
}
|
||||
existingPeer.localRefCount++
|
||||
return existingPeer
|
||||
}
|
||||
peers.table[peer.Name] = peer
|
||||
peer.IncrementLocalRefCount()
|
||||
peer.localRefCount++
|
||||
return peer
|
||||
}
|
||||
|
||||
@@ -71,6 +68,12 @@ func (peers *Peers) Fetch(name PeerName) (*Peer, bool) {
|
||||
return peer, found // GRRR, why can't I inline this!?
|
||||
}
|
||||
|
||||
func (peers *Peers) Dereference(peer *Peer) {
|
||||
peers.Lock()
|
||||
defer peers.Unlock()
|
||||
peer.localRefCount--
|
||||
}
|
||||
|
||||
func (peers *Peers) ForEach(fun func(*Peer)) {
|
||||
peers.RLock()
|
||||
defer peers.RUnlock()
|
||||
@@ -162,22 +165,11 @@ func (peers *Peers) String() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (peers *Peers) fetchAlias(peer *Peer) (*Peer, bool) {
|
||||
if existingPeer, found := peers.table[peer.Name]; found {
|
||||
if existingPeer.UID != peer.UID {
|
||||
return nil, true
|
||||
}
|
||||
existingPeer.IncrementLocalRefCount()
|
||||
return existingPeer, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (peers *Peers) garbageCollect() []*Peer {
|
||||
removed := []*Peer{}
|
||||
_, reached := peers.ourself.Routes(nil, false)
|
||||
for name, peer := range peers.table {
|
||||
if _, found := reached[peer.Name]; !found && !peer.IsLocallyReferenced() {
|
||||
if _, found := reached[peer.Name]; !found && peer.localRefCount == 0 {
|
||||
delete(peers.table, name)
|
||||
peers.onGC(peer)
|
||||
removed = append(removed, peer)
|
||||
|
||||
Reference in new issue
Block a user