github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/pidset.go (about)

     1  package actor
     2  
     3  type PIDSet struct {
     4  	pids   []*PID
     5  	lookup map[pidKey]int
     6  }
     7  
     8  // pidKey is used as a key in the lookup map to avoid allocations.
     9  type pidKey struct {
    10  	address string
    11  	id      string
    12  }
    13  
    14  func (p *PIDSet) key(pid *PID) pidKey {
    15  	return pidKey{address: pid.Address, id: pid.Id}
    16  }
    17  
    18  // NewPIDSet returns a new PIDSet with the given pids.
    19  func NewPIDSet(pids ...*PID) *PIDSet {
    20  	p := &PIDSet{}
    21  	for _, pid := range pids {
    22  		p.Add(pid)
    23  	}
    24  	return p
    25  }
    26  
    27  func (p *PIDSet) ensureInit() {
    28  	if p.lookup == nil {
    29  		p.lookup = make(map[pidKey]int)
    30  	}
    31  }
    32  
    33  func (p *PIDSet) indexOf(v *PID) int {
    34  	if idx, ok := p.lookup[p.key(v)]; ok {
    35  		return idx
    36  	}
    37  
    38  	return -1
    39  }
    40  
    41  func (p *PIDSet) Contains(v *PID) bool {
    42  	_, ok := p.lookup[p.key(v)]
    43  	return ok
    44  }
    45  
    46  // Add adds the element v to the set.
    47  func (p *PIDSet) Add(v *PID) {
    48  	p.ensureInit()
    49  	if p.Contains(v) {
    50  		return
    51  	}
    52  
    53  	p.pids = append(p.pids, v)
    54  	p.lookup[p.key(v)] = len(p.pids) - 1
    55  }
    56  
    57  // Remove removes v from the set and returns true if them element existed.
    58  func (p *PIDSet) Remove(v *PID) bool {
    59  	p.ensureInit()
    60  	i := p.indexOf(v)
    61  	if i == -1 {
    62  		return false
    63  	}
    64  
    65  	delete(p.lookup, p.key(v))
    66  	if i < len(p.pids)-1 {
    67  		lastPID := p.pids[len(p.pids)-1]
    68  
    69  		p.pids[i] = lastPID
    70  		p.lookup[p.key(lastPID)] = i
    71  	}
    72  
    73  	p.pids = p.pids[:len(p.pids)-1]
    74  
    75  	return true
    76  }
    77  
    78  // Len returns the number of elements in the set.
    79  func (p *PIDSet) Len() int {
    80  	return len(p.pids)
    81  }
    82  
    83  // Clear removes all the elements in the set.
    84  func (p *PIDSet) Clear() {
    85  	p.pids = p.pids[:0]
    86  	p.lookup = make(map[pidKey]int)
    87  }
    88  
    89  // Empty reports whether the set is empty.
    90  func (p *PIDSet) Empty() bool {
    91  	return p.Len() == 0
    92  }
    93  
    94  // Values returns all the elements of the set as a slice.
    95  func (p *PIDSet) Values() []*PID {
    96  	return p.pids
    97  }
    98  
    99  // ForEach invokes f for every element of the set.
   100  func (p *PIDSet) ForEach(f func(i int, pid *PID)) {
   101  	for i, pid := range p.pids {
   102  		f(i, pid)
   103  	}
   104  }
   105  
   106  func (p *PIDSet) Get(index int) *PID {
   107  	return p.pids[index]
   108  }
   109  
   110  func (p *PIDSet) Clone() *PIDSet {
   111  	return NewPIDSet(p.pids...)
   112  }