vitess.io/vitess@v0.16.2/go/timer/suspendable_ticker.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package timer 18 19 import ( 20 "sync/atomic" 21 "time" 22 ) 23 24 // SuspendableTicker is similar to time.Ticker, but also offers Suspend() and Resume() functions. 25 // While the ticker is suspended, nothing comes from the time channel C 26 type SuspendableTicker struct { 27 ticker *time.Ticker 28 // C is user facing 29 C chan time.Time 30 31 suspended int64 32 } 33 34 // NewSuspendableTicker creates a new suspendable ticker, indicating whether the ticker should start 35 // suspendable or running 36 func NewSuspendableTicker(d time.Duration, initiallySuspended bool) *SuspendableTicker { 37 s := &SuspendableTicker{ 38 ticker: time.NewTicker(d), 39 C: make(chan time.Time), 40 } 41 if initiallySuspended { 42 s.suspended = 1 43 } 44 go s.loop() 45 return s 46 } 47 48 // Suspend stops sending time events on the channel C 49 // time events sent during suspended time are lost 50 func (s *SuspendableTicker) Suspend() { 51 atomic.StoreInt64(&s.suspended, 1) 52 } 53 54 // Resume re-enables time events on channel C 55 func (s *SuspendableTicker) Resume() { 56 atomic.StoreInt64(&s.suspended, 0) 57 } 58 59 // Stop completely stops the timer, like time.Timer 60 func (s *SuspendableTicker) Stop() { 61 s.ticker.Stop() 62 } 63 64 // TickNow generates a tick at this point in time. It may block 65 // if nothing consumes the tick. 66 func (s *SuspendableTicker) TickNow() { 67 if atomic.LoadInt64(&s.suspended) == 0 { 68 // not suspended 69 s.C <- time.Now() 70 } 71 } 72 73 func (s *SuspendableTicker) loop() { 74 for t := range s.ticker.C { 75 if atomic.LoadInt64(&s.suspended) == 0 { 76 // not suspended 77 s.C <- t 78 } 79 } 80 }