kwg.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // package kwg -- именованный ожидатель потоков ядра.
  2. //
  3. // Не позволяет завершиться ядру, если есть хоть один работающий поток
  4. package kwg
  5. import (
  6. "context"
  7. "time"
  8. "gitp78su.ipnodns.ru/svi/kern/v4/d0"
  9. "gitp78su.ipnodns.ru/svi/kern/v4/d1"
  10. "gitp78su.ipnodns.ru/svi/kern/v4/d2/kern_ent/stream_name"
  11. )
  12. // KernWg -- именованный ожидатель потоков ядра.
  13. type KernWg struct {
  14. *d0.MSafeMutex
  15. owner *d0.LOwner
  16. ctx context.Context
  17. dictStream map[*stream_name.AStreamName]d0.Bool // Словарь имён потоков с признаком работы
  18. isWork *d0.MSafeBool
  19. log *d1.LogBuf
  20. }
  21. var (
  22. kernWg *KernWg // Глобальный объект
  23. block = d0.MutSafeMutex()
  24. )
  25. // GetKernelWg -- возвращает новый именованный ожидатель потоков ядра.
  26. func GetKernelWg(ctx context.Context) *KernWg {
  27. block.Lock()
  28. defer block.Unlock()
  29. if kernWg != nil {
  30. kernWg.log.Debug("GetKernelWg()")
  31. return kernWg
  32. }
  33. owner := d0.LetOwner(1, "isol_kern_wg")
  34. d0.If(ctx == nil).Hassert("GetKernelWg(): ctx==nil")
  35. paramLogBuf := &d1.LogBufParam{
  36. Owner_:owner,
  37. IsTerm_: d0.MutSafeBool(owner, true),
  38. Prefix_: d0.LetTxt(owner, "kernelWg"),
  39. }
  40. sf := &KernWg{
  41. MSafeMutex: d0.MutSafeMutex(),
  42. owner: owner,
  43. ctx: ctx,
  44. dictStream: map[*stream_name.AStreamName]d0.Bool{},
  45. isWork: d0.MutSafeBool(owner, false),
  46. log: d1.NewLogBuf(paramLogBuf),
  47. }
  48. sf.log.Debug("GetKernelWg(): run")
  49. go sf.close()
  50. sf.isWork.Set()
  51. kernWg = sf
  52. return kernWg
  53. }
  54. // Log -- возвращает лог ожидателя потоков.
  55. func (sf *KernWg) Log() *d1.LogBuf {
  56. return sf.log
  57. }
  58. // Len -- возвращает размер списка ожидания потоков.
  59. func (sf *KernWg) Len() d0.Num {
  60. sf.RLock()
  61. defer sf.RUnlock()
  62. return d0.Num(len(sf.dictStream))
  63. }
  64. // IsWork -- возвращает признак работы ядра.
  65. func (sf *KernWg) IsWork() d0.Bool {
  66. return sf.isWork.IsOk()
  67. }
  68. // IsStop -- возвращает признак остановки ядра.
  69. func (sf *KernWg) IsStop() d0.Bool {
  70. return !sf.isWork.IsOk()
  71. }
  72. // List -- возвращает список имён потоков на ожидании.
  73. func (sf *KernWg) List() []*stream_name.AStreamName {
  74. sf.RLock()
  75. defer sf.RUnlock()
  76. lst := make([]*stream_name.AStreamName, 0, len(sf.dictStream))
  77. for name := range sf.dictStream {
  78. lst = append(lst, name)
  79. }
  80. return lst
  81. }
  82. // Done -- удаляет поток из ожидания.
  83. func (sf *KernWg) Done(name *stream_name.AStreamName) {
  84. sf.Lock()
  85. defer sf.Unlock()
  86. delete(sf.dictStream, name)
  87. sf.log.Debug("Done(): stream(%v) done", name)
  88. }
  89. // Wait -- блокирующий вызов; возвращает управление, только когда все потоки завершили работу.
  90. func (sf *KernWg) Wait() {
  91. for {
  92. time.Sleep(time.Millisecond * 1)
  93. if sf.isWork.IsNot() {
  94. break
  95. }
  96. }
  97. sf.log.Debug("Wait(): done")
  98. }
  99. // Add -- добавляет поток в ожидание.
  100. func (sf *KernWg) Add(name *stream_name.AStreamName) {
  101. sf.Lock()
  102. defer sf.Unlock()
  103. sf.log.Debug("Add(): stream('%v') done", name)
  104. d0.If(sf.isWork.IsNot()).Hassert("Add(): stream=%v, work end", []any{name})
  105. d0.If(name.Get() == "").Hassert("Add(): name stream is empty")
  106. _, isOk := sf.dictStream[name]
  107. d0.If(d0.Bool(isOk)).Hassert("Add(): stream '%v' already exists", name)
  108. sf.dictStream[name] = true
  109. }
  110. // Ожидает окончания работы ожидателя групп.
  111. func (sf *KernWg) close() {
  112. <-sf.ctx.Done()
  113. fnDone := func() bool {
  114. sf.Lock()
  115. defer sf.Unlock()
  116. return len(sf.dictStream) == 0
  117. }
  118. for {
  119. time.Sleep(time.Millisecond * 1)
  120. if fnDone() {
  121. break
  122. }
  123. }
  124. sf.Lock()
  125. defer sf.Unlock()
  126. if sf.isWork.IsNot() {
  127. return
  128. }
  129. sf.isWork.Reset()
  130. sf.log.Debug("close(): end")
  131. }