84 lines
1.5 KiB
Go
84 lines
1.5 KiB
Go
package utilities
|
|
|
|
import (
|
|
"math"
|
|
"math/rand/v2"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ApplyJitter = DefaultApplyJitter
|
|
)
|
|
|
|
const (
|
|
maxInt64 = math.MaxInt64
|
|
minInt64 = math.MinInt64
|
|
)
|
|
|
|
func satAdd(a, b int64) int64 {
|
|
switch {
|
|
case b > 0 && a > maxInt64-b:
|
|
return maxInt64
|
|
case b < 0 && a < minInt64-b:
|
|
return minInt64
|
|
default:
|
|
return a + b
|
|
}
|
|
}
|
|
|
|
func satSub(a, b int64) int64 {
|
|
switch {
|
|
case b > 0 && a < minInt64+b:
|
|
return minInt64
|
|
case b < 0 && a > maxInt64+b:
|
|
return maxInt64
|
|
default:
|
|
return a - b
|
|
}
|
|
}
|
|
|
|
func absDurationSat(d time.Duration) time.Duration {
|
|
if d >= 0 {
|
|
return d
|
|
}
|
|
if d == time.Duration(math.MinInt64) {
|
|
return time.Duration(math.MaxInt64)
|
|
}
|
|
return -d
|
|
}
|
|
|
|
func DefaultApplyJitter(pauseDuration time.Duration, jitter time.Duration) time.Duration {
|
|
switch {
|
|
case pauseDuration <= 0:
|
|
return 0
|
|
case jitter == 0:
|
|
return pauseDuration
|
|
case jitter < 0:
|
|
jitter = absDurationSat(jitter)
|
|
case jitter > pauseDuration:
|
|
pauseDuration, jitter = jitter, pauseDuration
|
|
}
|
|
min := satSub(pauseDuration.Nanoseconds(), jitter.Nanoseconds())
|
|
if min < 0 {
|
|
min = 0
|
|
}
|
|
max := satAdd(pauseDuration.Nanoseconds(), jitter.Nanoseconds())
|
|
if max <= min {
|
|
return time.Duration(min)
|
|
}
|
|
|
|
var maxExcl int64
|
|
if max == math.MaxInt64 {
|
|
span := max - min
|
|
if span == math.MaxInt64 {
|
|
return time.Duration(rand.Int64N(math.MaxInt64) + min)
|
|
}
|
|
n := rand.Int64N(span + 1)
|
|
return time.Duration(min + n)
|
|
}
|
|
|
|
maxExcl = max + 1
|
|
return time.Duration(min + rand.Int64N(maxExcl-min))
|
|
|
|
}
|