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:
Matthias Radestock committed 2015-05-11 17:19:23 +01:00
1 parent 3e6eef5ebd
commit 505ced5cc8
5 files changed
+19 -45

No files matched your search

+1 -1
View File
@@ -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)
}
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)