clash/common/singledo/singledo.go

65 lines
1 KiB
Go
Raw Normal View History

package singledo
import (
"sync"
"time"
)
type call struct {
wg sync.WaitGroup
2022-03-16 04:10:13 +00:00
val any
err error
}
type Single struct {
mux sync.Mutex
2019-12-10 08:26:15 +00:00
last time.Time
wait time.Duration
call *call
result *Result
}
type Result struct {
2022-03-16 04:10:13 +00:00
Val any
Err error
}
2020-10-14 11:56:02 +00:00
// Do single.Do likes sync.singleFlight
//lint:ignore ST1008 it likes sync.singleFlight
2022-03-16 04:10:13 +00:00
func (s *Single) Do(fn func() (any, error)) (v any, err error, shared bool) {
s.mux.Lock()
2019-12-10 08:26:15 +00:00
now := time.Now()
if now.Before(s.last.Add(s.wait)) {
s.mux.Unlock()
return s.result.Val, s.result.Err, true
}
if call := s.call; call != nil {
s.mux.Unlock()
call.wg.Wait()
return call.val, call.err, true
}
call := &call{}
call.wg.Add(1)
s.call = call
s.mux.Unlock()
call.val, call.err = fn()
2019-12-10 08:26:15 +00:00
call.wg.Done()
2020-07-18 12:56:13 +00:00
s.mux.Lock()
s.call = nil
s.result = &Result{call.val, call.err}
s.last = now
2020-07-18 12:56:13 +00:00
s.mux.Unlock()
return call.val, call.err, false
}
2020-04-30 12:13:27 +00:00
func (s *Single) Reset() {
s.last = time.Time{}
}
func NewSingle(wait time.Duration) *Single {
2019-12-10 08:26:15 +00:00
return &Single{wait: wait}
}