Consider special-casing timer channels created with time.Ticker and time.After.
Namely, such chans need to contain next fire time and period. Then receive from such
looks like:
func chanrecv(c *Hchan) {
...
if c.isTimeChan {
for {
next := c.nextTime
if next == -1 {
// already fired one-time timer
blockForever()
}
newTime := -1
if c.period != 0 {
newTime = next + c.period
}
if CAS(&c.nextTime, next, newTime) {
wait := next - now
if wait > 0 {
sleepFor(wait)
}
return
}
}
}
...
}
This has several advantages:
1. No need to stop timers. If nobody waits on a timers, it's just a normal heap object
that can be garbage collected.
2. Faster operation for both blocking and non-blocking case.
3. Faster selects involving time chans.
4. Can combine time.Ticker/After into a single allocation.
Consider special-casing timer channels created with time.Ticker and time.After. Namely, such chans need to contain next fire time and period. Then receive from such looks like: func chanrecv(c *Hchan) { ... if c.isTimeChan { for { next := c.nextTime if next == -1 { // already fired one-time timer blockForever() } newTime := -1 if c.period != 0 { newTime = next + c.period } if CAS(&c.nextTime, next, newTime) { wait := next - now if wait > 0 { sleepFor(wait) } return } } } ... } This has several advantages: 1. No need to stop timers. If nobody waits on a timers, it's just a normal heap object that can be garbage collected. 2. Faster operation for both blocking and non-blocking case. 3. Faster selects involving time chans. 4. Can combine time.Ticker/After into a single allocation.