github.com/gogf/gf/v2@v2.7.4/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/gogf/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  	var (
    14  		currentTimerTicks   int64
    15  		timerIntervalTicker = time.NewTicker(t.options.Interval)
    16  	)
    17  	defer timerIntervalTicker.Stop()
    18  	for {
    19  		select {
    20  		case <-timerIntervalTicker.C:
    21  			// Check the timer status.
    22  			switch t.status.Val() {
    23  			case StatusRunning:
    24  				// Timer proceeding.
    25  				if currentTimerTicks = t.ticks.Add(1); currentTimerTicks >= t.queue.NextPriority() {
    26  					t.proceed(currentTimerTicks)
    27  				}
    28  
    29  			case StatusStopped:
    30  				// Do nothing.
    31  
    32  			case StatusClosed:
    33  				// Timer exits.
    34  				return
    35  			}
    36  		}
    37  	}
    38  }
    39  
    40  // proceed function proceeds the timer job checking and running logic.
    41  func (t *Timer) proceed(currentTimerTicks int64) {
    42  	var value interface{}
    43  	for {
    44  		value = t.queue.Pop()
    45  		if value == nil {
    46  			break
    47  		}
    48  		entry := value.(*Entry)
    49  		// It checks if it meets the ticks' requirement.
    50  		if jobNextTicks := entry.nextTicks.Val(); currentTimerTicks < jobNextTicks {
    51  			// It pushes the job back if current ticks does not meet its running ticks requirement.
    52  			t.queue.Push(entry, entry.nextTicks.Val())
    53  			break
    54  		}
    55  		// It checks the job running requirements and then does asynchronous running.
    56  		entry.doCheckAndRunByTicks(currentTimerTicks)
    57  		// Status check: push back or ignore it.
    58  		if entry.Status() != StatusClosed {
    59  			// It pushes the job back to queue for next running.
    60  			t.queue.Push(entry, entry.nextTicks.Val())
    61  		}
    62  	}
    63  }