7 // IPeerSet has a (immutable) subset of the methods of PeerSet.
8 type IPeerSet interface {
15 //-----------------------------------------------------------------------------
17 // PeerSet is a special structure for keeping a table of peers.
18 // Iteration over the peers is super fast and thread-safe.
21 lookup map[string]*peerSetItem
25 type peerSetItem struct {
30 func NewPeerSet() *PeerSet {
32 lookup: make(map[string]*peerSetItem),
33 list: make([]*Peer, 0, 256),
37 // Returns false if peer with key (PubKeyEd25519) is already set
38 func (ps *PeerSet) Add(peer *Peer) error {
41 if ps.lookup[peer.Key] != nil {
42 return ErrSwitchDuplicatePeer
46 // Appending is safe even with other goroutines
47 // iterating over the ps.list slice.
48 ps.list = append(ps.list, peer)
49 ps.lookup[peer.Key] = &peerSetItem{peer, index}
53 func (ps *PeerSet) Has(peerKey string) bool {
56 _, ok := ps.lookup[peerKey]
60 func (ps *PeerSet) Get(peerKey string) *Peer {
63 item, ok := ps.lookup[peerKey]
71 func (ps *PeerSet) Remove(peer *Peer) {
74 item := ps.lookup[peer.Key]
80 // Copy the list but without the last element.
81 // (we must copy because we're mutating the list)
82 newList := make([]*Peer, len(ps.list)-1)
83 copy(newList, ps.list)
84 // If it's the last peer, that's an easy special case.
85 if index == len(ps.list)-1 {
87 delete(ps.lookup, peer.Key)
91 // Move the last item from ps.list to "index" in list.
92 lastPeer := ps.list[len(ps.list)-1]
93 lastPeerKey := lastPeer.Key
94 lastPeerItem := ps.lookup[lastPeerKey]
95 newList[index] = lastPeer
96 lastPeerItem.index = index
98 delete(ps.lookup, peer.Key)
102 func (ps *PeerSet) Size() int {
104 defer ps.mtx.Unlock()
108 // threadsafe list of peers.
109 func (ps *PeerSet) List() []*Peer {
111 defer ps.mtx.Unlock()