mapx.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package tinymq
  2. // 一个简单的订阅查找匹配组件
  3. /* 优化连接方式
  4. - 高效匹配字符串算法
  5. - 随机匹配算法
  6. - 排序算法
  7. - 支持万级连接数
  8. */
  9. import (
  10. "math/rand"
  11. "sync"
  12. )
  13. type Mapx struct {
  14. sync.RWMutex
  15. id int // 生成 id 号
  16. lineMap map[int]*Line
  17. randLines []*Line
  18. }
  19. func NewMapx() *Mapx {
  20. return &Mapx{
  21. lineMap: make(map[int]*Line),
  22. randLines: make([]*Line, 0),
  23. }
  24. }
  25. // 存储连接
  26. func (m *Mapx) Store(line *Line) {
  27. m.Lock()
  28. defer m.Unlock()
  29. m.id++
  30. m.lineMap[m.id] = line
  31. m.randLines = append(m.randLines, line)
  32. if len(m.randLines) < 3 {
  33. return
  34. }
  35. // 交换一下位置,随机数组
  36. i := rand.Intn(len(m.randLines) - 1)
  37. t := m.randLines[i]
  38. m.randLines[i] = line
  39. m.randLines[len(m.randLines)-1] = t
  40. }
  41. // 删除连接
  42. func (m *Mapx) Delete(line *Line) {
  43. m.Lock()
  44. defer m.Unlock()
  45. for k, v := range m.lineMap {
  46. if v == line {
  47. delete(m.lineMap, k)
  48. break
  49. }
  50. }
  51. for i, v := range m.randLines {
  52. if v == line {
  53. l := len(m.randLines) - 1
  54. m.randLines[i] = m.randLines[l]
  55. m.randLines = m.randLines[0:l]
  56. break
  57. }
  58. }
  59. }
  60. // ID 方式删除连接
  61. func (m *Mapx) DeleteById(id int) {
  62. m.Lock()
  63. defer m.Unlock()
  64. line, ok := m.lineMap[id]
  65. if !ok {
  66. return
  67. }
  68. delete(m.lineMap, id)
  69. for i, v := range m.randLines {
  70. if v == line {
  71. l := len(m.randLines) - 1
  72. m.randLines[i] = m.randLines[l]
  73. m.randLines = m.randLines[0:l]
  74. break
  75. }
  76. }
  77. }
  78. // 删除不可用连接
  79. func (m *Mapx) DeleteInvalidLines(expired int64) {
  80. m.Lock()
  81. defer m.Unlock()
  82. for id, line := range m.lineMap {
  83. if line.updated.UnixMilli() < expired {
  84. delete(m.lineMap, id)
  85. }
  86. }
  87. for i := len(m.randLines) - 1; i >= 0; i-- {
  88. line := m.randLines[i]
  89. if line.updated.UnixMilli() < expired {
  90. l := len(m.randLines) - 1
  91. m.randLines[i] = m.randLines[l]
  92. m.randLines = m.randLines[0:l]
  93. }
  94. }
  95. }
  96. // 循环遍历
  97. func (m *Mapx) Range(fn func(id int, line *Line) bool) {
  98. m.RLock()
  99. defer m.RUnlock()
  100. for k, v := range m.lineMap {
  101. if !fn(k, v) {
  102. break
  103. }
  104. }
  105. }
  106. // 打乱随机数组
  107. func (m *Mapx) Rand() {
  108. m.Lock()
  109. defer m.Unlock()
  110. l := len(m.randLines) / 2
  111. for i := range l {
  112. k := rand.Intn(l) + l
  113. v := m.randLines[i]
  114. m.randLines[i] = m.randLines[k]
  115. m.randLines[k] = v
  116. }
  117. }
  118. // 随机遍历
  119. func (m *Mapx) RandRange(fn func(i int, v *Line) bool, rand bool) {
  120. if rand {
  121. m.Rand()
  122. }
  123. m.RLock()
  124. defer m.RUnlock()
  125. for i, v := range m.randLines {
  126. if !fn(i, v) {
  127. break
  128. }
  129. }
  130. }
  131. // 是否存在
  132. func (m *Mapx) Exist(line *Line) bool {
  133. for _, v := range m.lineMap {
  134. if v == line {
  135. return true
  136. }
  137. }
  138. return false
  139. }