vRp.CD2g_test/server/internal/v2/loadbalancer/round_robin.go

99 lines
1.5 KiB
Go

package loadbalancer
import "sync"
func NewRoundRobin[Id comparable, T RoundRobinItem[Id]]() *RoundRobin[Id, T] {
return &RoundRobin[Id, T]{
head: nil,
curr: nil,
size: 0,
}
}
type roundRobinNode[Id comparable, T RoundRobinItem[Id]] struct {
Value T
Next *roundRobinNode[Id, T]
}
type RoundRobin[Id comparable, T RoundRobinItem[Id]] struct {
head *roundRobinNode[Id, T]
curr *roundRobinNode[Id, T]
size int
rw sync.RWMutex
}
func (r *RoundRobin[Id, T]) Add(t T) {
r.rw.Lock()
defer r.rw.Unlock()
newNode := &roundRobinNode[Id, T]{Value: t}
if r.head == nil {
r.head = newNode
r.curr = newNode
newNode.Next = newNode
} else {
newNode.Next = r.head.Next
r.head.Next = newNode
}
r.size++
}
func (r *RoundRobin[Id, T]) Remove(t T) {
r.rw.Lock()
defer r.rw.Unlock()
if r.head == nil {
return
}
prev := r.head
for i := 0; i < r.size; i++ {
if prev.Next.Value.Id() == t.Id() {
if prev.Next == r.curr {
r.curr = prev
}
prev.Next = prev.Next.Next
r.size--
if r.size == 0 {
r.head = nil
r.curr = nil
}
return
}
prev = prev.Next
}
}
func (r *RoundRobin[Id, T]) Next() (t T) {
r.rw.Lock()
defer r.rw.Unlock()
if r.curr == nil {
return
}
r.curr = r.curr.Next
return r.curr.Value
}
func (r *RoundRobin[Id, T]) Refresh() {
r.rw.Lock()
defer r.rw.Unlock()
if r.head == nil {
return
}
curr := r.head
for i := 0; i < r.size; i++ {
if curr.Value.Id() == r.curr.Value.Id() {
r.curr = curr
return
}
curr = curr.Next
}
r.curr = r.head
}