-
Notifications
You must be signed in to change notification settings - Fork 6
/
tick.go
130 lines (112 loc) · 2.15 KB
/
tick.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package timer
import (
"sync/atomic"
"time"
"github.com/singchia/go-timer/v2/pkg/linker"
)
type tickOption struct {
data interface{}
ch chan *Event
chOutside bool
handler func(*Event)
cyclically bool
}
type status int
const (
statusAdd = iota
statusWait
statusFire
statusCanceled
)
// the real shit
type tick struct {
// user interface
*tickOption
// location
id linker.DoubID
s *slot
tw *timingwheel
ipw []uint
// meta
duration time.Duration
delay time.Duration
insertTime time.Time
// status
fired int64
status status
}
// TODO revision
func (t *tick) Reset(data interface{}) error {
t.tw.mtx.RLock()
defer t.tw.mtx.RUnlock()
if t.tw.twStatus != twStatusStarted {
return ErrTimerNotStarted
}
ch := make(chan *operationRet)
t.tw.operations <- &operation{
tick: t,
operType: operReset,
retCh: ch,
data: data,
}
ret, ok := <-ch
if !ok {
return ErrOperationForceClosed
}
return ret.err
}
// Don't cancel the tick in timeout handler, it may cause the block when buffer is fulfilled.
// The cancel operation may not work when the tick is about to time up.
func (t *tick) Cancel() error {
t.tw.mtx.RLock()
defer t.tw.mtx.RUnlock()
if t.tw.twStatus != twStatusStarted {
return ErrTimerNotStarted
}
ch := make(chan *operationRet)
t.tw.operations <- &operation{
tick: t,
operType: operCancel,
retCh: ch,
}
ret, ok := <-ch
if !ok {
return ErrOperationForceClosed
}
return ret.err
}
// TODO revision
func (t *tick) Delay(d time.Duration) error {
if t.cyclically {
return ErrDelayOnCyclically
}
t.tw.mtx.RLock()
defer t.tw.mtx.RUnlock()
if t.tw.twStatus != twStatusStarted {
return ErrTimerNotStarted
}
ch := make(chan *operationRet)
t.tw.operations <- &operation{
tick: t,
operType: operDelay,
delay: d,
retCh: ch,
}
ret, ok := <-ch
if !ok {
return ErrOperationForceClosed
}
return ret.err
}
func (t *tick) Fired() int64 {
return atomic.LoadInt64(&t.fired)
}
func (t *tick) C() <-chan *Event {
return t.ch
}
func (t *tick) InsertTime() time.Time {
return t.insertTime
}
func (t *tick) Duration() time.Duration {
return t.duration
}