You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

task.go 2.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package task
  2. import (
  3. "sync"
  4. "sync/atomic"
  5. "time"
  6. mylo "gitlink.org.cn/cloudream/common/utils/lo"
  7. )
  8. type CompleteOption struct {
  9. // 在Task调用complete函数时调用。调用时被Manager的锁保护。
  10. Completing func()
  11. // 延迟删除Manager中的任务,为0时没有延迟,即在Task调用complete函数时立刻删除。
  12. RemovingDelay time.Duration
  13. }
  14. type CompleteFn = func(err error, opts ...CompleteOption)
  15. type TaskBody[TCtx any] interface {
  16. Execute(task *Task[TCtx], ctx TCtx, complete CompleteFn)
  17. }
  18. type ComparableTaskBody[TCtx any] interface {
  19. TaskBody[TCtx]
  20. Compare(other *Task[TCtx]) bool
  21. }
  22. type Task[TCtx any] struct {
  23. id string
  24. body TaskBody[TCtx]
  25. isCompleted atomic.Bool
  26. waiters []chan any
  27. onCompleted []func(task *Task[TCtx])
  28. waiterLock sync.Mutex
  29. err error
  30. }
  31. func (t *Task[TCtx]) ID() string {
  32. return t.id
  33. }
  34. func (t *Task[TCtx]) Body() TaskBody[TCtx] {
  35. return t.body
  36. }
  37. func (t *Task[TCtx]) IsCompleted() bool {
  38. // 设置err是在Store之前,所以isCompleted为true时一定能获得最新的err
  39. return t.isCompleted.Load()
  40. }
  41. func (t *Task[TCtx]) Error() error {
  42. return t.err
  43. }
  44. func (t *Task[TCtx]) Wait() {
  45. t.waiterLock.Lock()
  46. if t.isCompleted.Load() {
  47. t.waiterLock.Unlock()
  48. return
  49. }
  50. waiter := make(chan any)
  51. t.waiters = append(t.waiters, waiter)
  52. t.waiterLock.Unlock()
  53. <-waiter
  54. }
  55. // 限时等待,返回true代表等待成功,返回false代表等待超时
  56. func (t *Task[TCtx]) WaitTimeout(timeout time.Duration) bool {
  57. t.waiterLock.Lock()
  58. if t.isCompleted.Load() {
  59. t.waiterLock.Unlock()
  60. return true
  61. }
  62. waiter := make(chan any)
  63. t.waiters = append(t.waiters, waiter)
  64. t.waiterLock.Unlock()
  65. select {
  66. case <-time.After(timeout):
  67. t.waiterLock.Lock()
  68. t.waiters = mylo.Remove(t.waiters, waiter)
  69. t.waiterLock.Unlock()
  70. return false
  71. case <-waiter:
  72. return true
  73. }
  74. }
  75. func (t *Task[TCtx]) OnCompleted(callback func(task *Task[TCtx])) {
  76. t.waiterLock.Lock()
  77. if t.isCompleted.Load() {
  78. t.waiterLock.Unlock()
  79. callback(t)
  80. return
  81. }
  82. t.onCompleted = append(t.onCompleted, callback)
  83. t.waiterLock.Unlock()
  84. }