return nil
}
-func (t *Exprier) LoopCheck(key string, dru time.Duration, whenfail func(key string, e error)) (breakLoop func()) {
+func (t *Exprier) LoopCheck(key string, dru time.Duration, whenfail func(key string, e error)) (breakLoop func(), e error) {
breakLoop = func() {}
if t.Max <= 0 {
return
}
if key == "" {
+ e = ErrNoFound
whenfail(key, ErrNoFound)
return
}
if t.m.Len() >= t.Max {
+ e = ErrOverflow
whenfail(key, ErrOverflow)
return
}
- c := make(chan struct{})
+ var close atomic.Bool
t.m.Store(key, time.Now().Add(dru))
breakLoop = func() {
t.m.Delete(key)
- close(c)
+ close.Store(true)
}
go func() {
- for t.Max > 0 {
+ for !close.Load() && t.Max > 0 {
ey, ok := t.m.LoadV(key).(time.Time)
if !ok {
whenfail(key, ErrNoFound)
whenfail(key, ErrExprie)
return
}
- select {
- case <-c:
- return
- case <-time.After(time.Until(ey) + time.Second):
- }
+ time.Sleep(time.Until(ey) + time.Second)
}
}()
return
"io"
"net"
"net/http"
+ "strconv"
"strings"
"testing"
"time"
}
w.Write(data)
}
+
+func Test1(b *testing.T) {
+ exp := Exprier{Max: 10}
+
+ el := make(chan error, 100)
+ for i := 0; i < 20; i++ {
+ done, e := exp.LoopCheck(strconv.Itoa(i), time.Second*10, func(key string, e error) {
+ if e != nil {
+ el <- e
+ b.Log(key, e)
+ }
+ })
+ if e != nil {
+ b.Fatal(e)
+ }
+ done()
+ }
+
+ time.Sleep(time.Second * 3)
+
+ if len(el) > 0 {
+ b.Fatal(<-el)
+ }
+}