embed lock in segment

This commit is contained in:
vyzo 2019-05-17 12:37:46 +03:00
parent 08caa87351
commit 5ed17f0b79
2 changed files with 30 additions and 31 deletions

View File

@ -30,10 +30,13 @@ func (e *expiringAddr) ExpiredBy(t time.Time) bool {
type addrSegments [256]*addrSegment
type addrSegment struct {
size uint32
sync.RWMutex
lk sync.RWMutex
// Use pointers to save memory. Maps always leave some fraction of their
// space unused. storing the *values* directly in the map will
// drastically increase the space waste. In our case, by 6x.
addrs map[peer.ID]map[string]*expiringAddr
size uint32
}
func (s *addrSegments) get(id peer.ID) *addrSegment {
@ -43,10 +46,6 @@ func (s *addrSegments) get(id peer.ID) *addrSegment {
// memoryAddrBook manages addresses.
type memoryAddrBook struct {
addrmu sync.RWMutex
// Use pointers to save memory. Maps always leave some fraction of their
// space unused. storing the *values* directly in the map will
// drastically increase the space waste. In our case, by 6x.
segments addrSegments
ctx context.Context
@ -101,7 +100,7 @@ func (mab *memoryAddrBook) Close() error {
func (mab *memoryAddrBook) gc() {
now := time.Now()
for _, s := range mab.segments {
s.lk.Lock()
s.Lock()
for p, amap := range s.addrs {
for k, addr := range amap {
if addr.ExpiredBy(now) {
@ -113,7 +112,7 @@ func (mab *memoryAddrBook) gc() {
}
}
atomic.StoreUint32(&s.size, uint32(len(s.addrs)))
s.lk.Unlock()
s.Unlock()
}
}
@ -126,11 +125,11 @@ func (mab *memoryAddrBook) PeersWithAddrs() peer.IDSlice {
pids := make(peer.IDSlice, 0, length)
for _, s := range mab.segments {
s.lk.RLock()
s.RLock()
for pid, _ := range s.addrs {
pids = append(pids, pid)
}
s.lk.RUnlock()
s.RUnlock()
}
return pids
}
@ -150,8 +149,8 @@ func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du
}
s := mab.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
// update the segment size
defer atomic.StoreUint32(&s.size, uint32(len(s.addrs)))
@ -186,8 +185,8 @@ func (mab *memoryAddrBook) SetAddr(p peer.ID, addr ma.Multiaddr, ttl time.Durati
// This is used when we receive the best estimate of the validity of an address.
func (mab *memoryAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) {
s := mab.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
// update the segment size
defer atomic.StoreUint32(&s.size, uint32(len(s.addrs)))
@ -220,8 +219,8 @@ func (mab *memoryAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du
// the given oldTTL to have the given newTTL.
func (mab *memoryAddrBook) UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.Duration) {
s := mab.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
// update the segment size
defer atomic.StoreUint32(&s.size, uint32(len(s.addrs)))
@ -244,8 +243,8 @@ func (mab *memoryAddrBook) UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL t
// Addresses returns all known (and valid) addresses for a given
func (mab *memoryAddrBook) Addrs(p peer.ID) []ma.Multiaddr {
s := mab.segments.get(p)
s.lk.RLock()
defer s.lk.RUnlock()
s.RLock()
defer s.RUnlock()
amap, found := s.addrs[p]
if !found {
@ -266,8 +265,8 @@ func (mab *memoryAddrBook) Addrs(p peer.ID) []ma.Multiaddr {
// ClearAddrs removes all previously stored addresses
func (mab *memoryAddrBook) ClearAddrs(p peer.ID) {
s := mab.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
// update the segment size
defer atomic.StoreUint32(&s.size, uint32(len(s.addrs)))
@ -279,8 +278,8 @@ func (mab *memoryAddrBook) ClearAddrs(p peer.ID) {
// given peer ID will be published.
func (mab *memoryAddrBook) AddrStream(ctx context.Context, p peer.ID) <-chan ma.Multiaddr {
s := mab.segments.get(p)
s.lk.RLock()
defer s.lk.RUnlock()
s.RLock()
defer s.RUnlock()
baseaddrslice := s.addrs[p]
initial := make([]ma.Multiaddr, 0, len(baseaddrslice))

View File

@ -12,7 +12,7 @@ const maxInternedProtocols = 64
const maxInternedProtocolSize = 128
type protoSegment struct {
lk sync.RWMutex
sync.RWMutex
interned map[string]string
protocols map[peer.ID]map[string]struct{}
}
@ -63,8 +63,8 @@ func NewProtoBook() pstore.ProtoBook {
func (pb *memoryProtoBook) SetProtocols(p peer.ID, protos ...string) error {
s := pb.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
newprotos := make(map[string]struct{}, len(protos))
for _, proto := range protos {
@ -78,8 +78,8 @@ func (pb *memoryProtoBook) SetProtocols(p peer.ID, protos ...string) error {
func (pb *memoryProtoBook) AddProtocols(p peer.ID, protos ...string) error {
s := pb.segments.get(p)
s.lk.Lock()
defer s.lk.Unlock()
s.Lock()
defer s.Unlock()
protomap, ok := s.protocols[p]
if !ok {
@ -96,8 +96,8 @@ func (pb *memoryProtoBook) AddProtocols(p peer.ID, protos ...string) error {
func (pb *memoryProtoBook) GetProtocols(p peer.ID) ([]string, error) {
s := pb.segments.get(p)
s.lk.RLock()
defer s.lk.RUnlock()
s.RLock()
defer s.RUnlock()
out := make([]string, 0, len(s.protocols))
for k := range s.protocols[p] {
@ -109,8 +109,8 @@ func (pb *memoryProtoBook) GetProtocols(p peer.ID) ([]string, error) {
func (pb *memoryProtoBook) SupportsProtocols(p peer.ID, protos ...string) ([]string, error) {
s := pb.segments.get(p)
s.lk.RLock()
defer s.lk.RUnlock()
s.RLock()
defer s.RUnlock()
out := make([]string, 0, len(protos))
for _, proto := range protos {