sema.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package xugu
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. /*
  7. 定义信号量结构体:Sema 结构体包含一个 sync.Mutex 和一个 sync.Cond,以及一个计数器 count。
  8. 初始化信号量:initSema 和 initSemaN 函数用于初始化信号量,并设置信号量初始值。
  9. 减少信号量(等待):decSema 函数用于减少信号量,当信号量为 0 时阻塞。
  10. 增加信号量:incSema 函数用于增加信号量,并通知等待的 goroutine。
  11. 等待信号量:waitSema 函数调用 decSema 实现等待。
  12. 带超时的等待信号量:waitSemaT 函数实现带超时的等待信号量操作。
  13. 清除信号量:clrSema 函数将信号量计数器置为 0。
  14. 关闭信号量:在 Go 中不需要显式销毁信号量。
  15. 模拟 usleep 函数:sleep 函数使用 time.Sleep 模拟 usleep。
  16. */
  17. // 定义信号量结构体
  18. type Sema struct {
  19. mutex sync.Mutex
  20. cond *sync.Cond
  21. count int
  22. }
  23. // 初始化信号量
  24. func initSema() *Sema {
  25. sema := &Sema{}
  26. sema.cond = sync.NewCond(&sema.mutex)
  27. return sema
  28. }
  29. // 初始化信号量,并设置信号量初始值
  30. func initSemaN(n int) *Sema {
  31. sema := &Sema{count: n}
  32. sema.cond = sync.NewCond(&sema.mutex)
  33. return sema
  34. }
  35. // 减少信号量(等待)
  36. func (s *Sema) decSema() {
  37. s.mutex.Lock()
  38. for s.count == 0 {
  39. s.cond.Wait()
  40. }
  41. s.count--
  42. s.mutex.Unlock()
  43. }
  44. // 增加信号量
  45. func (s *Sema) incSema() {
  46. s.mutex.Lock()
  47. s.count++
  48. s.cond.Signal()
  49. s.mutex.Unlock()
  50. }
  51. // 等待信号量
  52. func (s *Sema) waitSema() {
  53. s.decSema()
  54. }
  55. // 带超时的等待信号量
  56. func (s *Sema) waitSemaT(timeout time.Duration) bool {
  57. s.mutex.Lock()
  58. defer s.mutex.Unlock()
  59. timer := time.NewTimer(timeout)
  60. defer timer.Stop()
  61. for s.count == 0 {
  62. timer.Reset(timeout)
  63. select {
  64. case <-timer.C:
  65. return false
  66. case <-func() chan struct{} {
  67. ch := make(chan struct{})
  68. go func() {
  69. s.cond.Wait()
  70. close(ch)
  71. }()
  72. return ch
  73. }():
  74. }
  75. }
  76. s.count--
  77. return true
  78. }
  79. // 清除信号量
  80. func (s *Sema) clrSema() {
  81. s.mutex.Lock()
  82. for s.count > 0 {
  83. s.count--
  84. }
  85. s.mutex.Unlock()
  86. }
  87. // 关闭信号量(销毁信号量)
  88. func (s *Sema) closeSema() {
  89. // 在 Go 中不需要显式销毁信号量
  90. }
  91. // 模拟 usleep 函数
  92. func sleep(t int) {
  93. time.Sleep(time.Duration(t) * time.Millisecond)
  94. }