github.com/gogf/gf@v1.16.9/os/gtimer/gtimer_entry.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 (
    10  	"github.com/gogf/gf/container/gtype"
    11  )
    12  
    13  // Entry is the timing job.
    14  type Entry struct {
    15  	job       JobFunc      // The job function.
    16  	timer     *Timer       // Belonged timer.
    17  	ticks     int64        // The job runs every tick.
    18  	times     *gtype.Int   // Limit running times.
    19  	status    *gtype.Int   // Job status.
    20  	singleton *gtype.Bool  // Singleton mode.
    21  	nextTicks *gtype.Int64 // Next run ticks of the job.
    22  	infinite  *gtype.Bool  // No times limit.
    23  }
    24  
    25  // JobFunc is the job function.
    26  type JobFunc = func()
    27  
    28  // Status returns the status of the job.
    29  func (entry *Entry) Status() int {
    30  	return entry.status.Val()
    31  }
    32  
    33  // Run runs the timer job asynchronously.
    34  func (entry *Entry) Run() {
    35  	if !entry.infinite.Val() {
    36  		leftRunningTimes := entry.times.Add(-1)
    37  		// It checks its running times exceeding.
    38  		if leftRunningTimes < 0 {
    39  			entry.status.Set(StatusClosed)
    40  			return
    41  		}
    42  	}
    43  	go func() {
    44  		defer func() {
    45  			if err := recover(); err != nil {
    46  				if err != panicExit {
    47  					panic(err)
    48  				} else {
    49  					entry.Close()
    50  					return
    51  				}
    52  			}
    53  			if entry.Status() == StatusRunning {
    54  				entry.SetStatus(StatusReady)
    55  			}
    56  		}()
    57  		entry.job()
    58  	}()
    59  }
    60  
    61  // doCheckAndRunByTicks checks the if job can run in given timer ticks,
    62  // it runs asynchronously if the given `currentTimerTicks` meets or else
    63  // it increments its ticks and waits for next running check.
    64  func (entry *Entry) doCheckAndRunByTicks(currentTimerTicks int64) {
    65  	// Ticks check.
    66  	if currentTimerTicks < entry.nextTicks.Val() {
    67  		return
    68  	}
    69  	entry.nextTicks.Set(currentTimerTicks + entry.ticks)
    70  	// Perform job checking.
    71  	switch entry.status.Val() {
    72  	case StatusRunning:
    73  		if entry.IsSingleton() {
    74  			return
    75  		}
    76  	case StatusReady:
    77  		if !entry.status.Cas(StatusReady, StatusRunning) {
    78  			return
    79  		}
    80  	case StatusStopped:
    81  		return
    82  	case StatusClosed:
    83  		return
    84  	}
    85  	// Perform job running.
    86  	entry.Run()
    87  }
    88  
    89  // SetStatus custom sets the status for the job.
    90  func (entry *Entry) SetStatus(status int) int {
    91  	return entry.status.Set(status)
    92  }
    93  
    94  // Start starts the job.
    95  func (entry *Entry) Start() {
    96  	entry.status.Set(StatusReady)
    97  }
    98  
    99  // Stop stops the job.
   100  func (entry *Entry) Stop() {
   101  	entry.status.Set(StatusStopped)
   102  }
   103  
   104  // Close closes the job, and then it will be removed from the timer.
   105  func (entry *Entry) Close() {
   106  	entry.status.Set(StatusClosed)
   107  }
   108  
   109  // Reset resets the job, which resets its ticks for next running.
   110  func (entry *Entry) Reset() {
   111  	entry.nextTicks.Set(entry.timer.ticks.Val() + entry.ticks)
   112  }
   113  
   114  // IsSingleton checks and returns whether the job in singleton mode.
   115  func (entry *Entry) IsSingleton() bool {
   116  	return entry.singleton.Val()
   117  }
   118  
   119  // SetSingleton sets the job singleton mode.
   120  func (entry *Entry) SetSingleton(enabled bool) {
   121  	entry.singleton.Set(enabled)
   122  }
   123  
   124  // Job returns the job function of this job.
   125  func (entry *Entry) Job() JobFunc {
   126  	return entry.job
   127  }
   128  
   129  // SetTimes sets the limit running times for the job.
   130  func (entry *Entry) SetTimes(times int) {
   131  	entry.times.Set(times)
   132  	entry.infinite.Set(false)
   133  }