eventloop.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package core
  2. import (
  3. "time"
  4. "kumachan/standalone/qt"
  5. "kumachan/standalone/ctn"
  6. )
  7. type EventLoop struct {
  8. tasks chan func()
  9. timers *timerHeap
  10. }
  11. func CreateEventLoop() *EventLoop {
  12. var e = &EventLoop {
  13. tasks: make(chan func(), 256),
  14. timers: createTimerHeap(),
  15. }
  16. go (func() {
  17. for {
  18. select {
  19. case k := <- e.tasks:
  20. qt.Schedule(k)
  21. default:
  22. select {
  23. case k := <- e.tasks:
  24. qt.Schedule(k)
  25. case <- e.timers.notify:
  26. if k, ok := e.timers.shift(); ok {
  27. qt.Schedule(k)
  28. }
  29. case f := <- e.timers.modify:
  30. f()
  31. }
  32. }
  33. }
  34. })()
  35. return e
  36. }
  37. func (e *EventLoop) addTask(k func()) {
  38. e.tasks <- k
  39. }
  40. func (e *EventLoop) addTimer(ms int, n int, ctx *context, k func()) {
  41. e.timers.modify <- func() {
  42. var dur = (time.Millisecond * time.Duration(ms))
  43. e.timers.insert(dur, n, ctx, k)
  44. }
  45. }
  46. type timerHeap struct {
  47. data ctn.MutHeap[*timer]
  48. notify <- chan time.Time
  49. modify chan func()
  50. }
  51. type timer struct {
  52. baseTime time.Time
  53. duration time.Duration
  54. repeat int
  55. context *context
  56. callback func()
  57. }
  58. func timerDue(a *timer) (bool,time.Duration) {
  59. var delta = time.Now().Sub(a.baseTime)
  60. return (delta >= a.duration), (a.duration - delta)
  61. }
  62. func timerLessThan(a *timer, b *timer) bool {
  63. return (a.baseTime.Sub(b.baseTime) < (b.duration - a.duration))
  64. }
  65. func createTimerHeap() *timerHeap {
  66. return &timerHeap {
  67. data: ctn.MakeMutHeap(timerLessThan),
  68. notify: nil,
  69. modify: make(chan func(), 256),
  70. }
  71. }
  72. func (h *timerHeap) shift() (func(), bool) {
  73. var first, ok = h.data.First()
  74. if !(ok) {
  75. return nil, false
  76. }
  77. { var due, dur = timerDue(first)
  78. if !(due) {
  79. h.notify = time.After(dur)
  80. return nil, false
  81. }}
  82. var this = first
  83. h.data.Shift()
  84. defer (func() {
  85. if first, ok := h.data.First(); ok {
  86. var due, dur = timerDue(first)
  87. if due {
  88. h.notify = time.After(0)
  89. } else {
  90. h.notify = time.After(dur)
  91. }
  92. }
  93. })()
  94. if this.context.isDisposed() {
  95. return nil, false
  96. }
  97. if this.repeat != 0 {
  98. var new_repeat_count int
  99. if this.repeat < 0 {
  100. // infinite
  101. new_repeat_count = this.repeat
  102. } else {
  103. new_repeat_count = (this.repeat - 1)
  104. }
  105. var repeat = &timer {
  106. baseTime: time.Now(),
  107. duration: this.duration,
  108. repeat: new_repeat_count,
  109. context: this.context,
  110. callback: this.callback,
  111. }
  112. h.data.Insert(repeat)
  113. }
  114. return this.callback, true
  115. }
  116. func (h *timerHeap) insert(dur time.Duration, n int, ctx *context, k func()) {
  117. if n == 0 {
  118. return
  119. }
  120. if dur < 0 {
  121. dur = 0
  122. }
  123. var a = &timer {
  124. baseTime: time.Now(),
  125. duration: dur,
  126. repeat: (n - 1),
  127. context: ctx,
  128. callback: k,
  129. }
  130. var first, has_first_before = h.data.First()
  131. h.data.Insert(a)
  132. if !(has_first_before) || (has_first_before && timerLessThan(a, first)) {
  133. h.notify = time.After(dur)
  134. }
  135. }