dae/component/outbound/dialer/latencies_n.go
2024-01-04 17:28:16 +08:00

62 lines
1.4 KiB
Go

/*
* SPDX-License-Identifier: AGPL-3.0-only
* Copyright (c) 2022-2024, daeuniverse Organization <dae@v2raya.org>
*/
package dialer
import (
"container/list"
"sync"
"time"
)
type LatenciesN struct {
N int
LastNLatencies *list.List
SumNLatencies time.Duration
mu sync.Mutex
}
func NewLatenciesN(n int) *LatenciesN {
return &LatenciesN{
N: n,
LastNLatencies: list.New(),
SumNLatencies: 0,
}
}
// AppendLatency appends a new latency to the back and keep the number in the list. Appending a fixed duration for
// failed or timeout situation is recommended.
//
// It is thread-safe.
func (ln *LatenciesN) AppendLatency(l time.Duration) {
ln.mu.Lock()
defer ln.mu.Unlock()
if ln.LastNLatencies.Len() >= ln.N {
ln.SumNLatencies -= ln.LastNLatencies.Front().Value.(time.Duration)
ln.LastNLatencies.Remove(ln.LastNLatencies.Front())
}
ln.SumNLatencies += l
ln.LastNLatencies.PushBack(l)
}
func (ln *LatenciesN) LastLatency() (time.Duration, bool) {
ln.mu.Lock()
defer ln.mu.Unlock()
if ln.LastNLatencies.Len() == 0 {
return 0, false
}
return ln.LastNLatencies.Back().Value.(time.Duration), true
}
func (ln *LatenciesN) AvgLatency() (time.Duration, bool) {
ln.mu.Lock()
defer ln.mu.Unlock()
if ln.LastNLatencies.Len() == 0 {
return 0, false
}
return ln.SumNLatencies / time.Duration(ln.LastNLatencies.Len()), true
}