github.com/wangyougui/gf/v2@v2.6.5/os/gtimer/gtimer_timer_loop.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package gtimer
     8  
     9  import "time"
    10  
    11  // loop starts the ticker using a standalone goroutine.
    12  func (t *Timer) loop() {
    13  	go func() {
    14  		var (
    15  			currentTimerTicks   int64
    16  			timerIntervalTicker = time.NewTicker(t.options.Interval)
    17  		)
    18  		defer timerIntervalTicker.Stop()
    19  		for {
    20  			select {
    21  			case <-timerIntervalTicker.C:
    22  				// Check the timer status.
    23  				switch t.status.Val() {
    24  				case StatusRunning:
    25  					// Timer proceeding.
    26  					if currentTimerTicks = t.ticks.Add(1); currentTimerTicks >= t.queue.NextPriority() {
    27  						t.proceed(currentTimerTicks)
    28  					}
    29  
    30  				case StatusStopped:
    31  					// Do nothing.
    32  
    33  				case StatusClosed:
    34  					// Timer exits.
    35  					return
    36  				}
    37  			}
    38  		}
    39  	}()
    40  }
    41  
    42  // proceed function proceeds the timer job checking and running logic.
    43  func (t *Timer) proceed(currentTimerTicks int64) {
    44  	var (
    45  		value interface{}
    46  	)
    47  	for {
    48  		value = t.queue.Pop()
    49  		if value == nil {
    50  			break
    51  		}
    52  		entry := value.(*Entry)
    53  		// It checks if it meets the ticks' requirement.
    54  		if jobNextTicks := entry.nextTicks.Val(); currentTimerTicks < jobNextTicks {
    55  			// It pushes the job back if current ticks does not meet its running ticks requirement.
    56  			t.queue.Push(entry, entry.nextTicks.Val())
    57  			break
    58  		}
    59  		// It checks the job running requirements and then does asynchronous running.
    60  		entry.doCheckAndRunByTicks(currentTimerTicks)
    61  		// Status check: push back or ignore it.
    62  		if entry.Status() != StatusClosed {
    63  			// It pushes the job back to queue for next running.
    64  			t.queue.Push(entry, entry.nextTicks.Val())
    65  		}
    66  	}
    67  }