gtimer_entry.go 3.2 KB

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