mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-05-13 13:35:59 +08:00
feat: cache add single-flight and timing-wheel.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package localcache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Execute[K comparable, V any] func(K, V)
|
||||
|
||||
type Task[K comparable, V any] struct {
|
||||
key K
|
||||
value V
|
||||
}
|
||||
|
||||
type TimeWheel[K comparable, V any] struct {
|
||||
ticker *time.Ticker
|
||||
slots [][]Task[K, V]
|
||||
currentPos int
|
||||
size int
|
||||
slotMutex sync.Mutex
|
||||
execute Execute[K, V]
|
||||
}
|
||||
|
||||
func NewTimeWheel[K comparable, V any](size int, tickDuration time.Duration, execute Execute[K, V]) *TimeWheel[K, V] {
|
||||
return &TimeWheel[K, V]{
|
||||
ticker: time.NewTicker(tickDuration),
|
||||
slots: make([][]Task[K, V], size),
|
||||
currentPos: 0,
|
||||
size: size,
|
||||
execute: execute,
|
||||
}
|
||||
}
|
||||
|
||||
func (tw *TimeWheel[K, V]) Start() {
|
||||
for range tw.ticker.C {
|
||||
tw.tick()
|
||||
}
|
||||
}
|
||||
|
||||
func (tw *TimeWheel[K, V]) Stop() {
|
||||
tw.ticker.Stop()
|
||||
}
|
||||
|
||||
func (tw *TimeWheel[K, V]) tick() {
|
||||
tw.slotMutex.Lock()
|
||||
defer tw.slotMutex.Unlock()
|
||||
|
||||
tasks := tw.slots[tw.currentPos]
|
||||
tw.slots[tw.currentPos] = nil
|
||||
if len(tasks) > 0 {
|
||||
go func(tasks []Task[K, V]) {
|
||||
for _, task := range tasks {
|
||||
tw.execute(task.key, task.value)
|
||||
}
|
||||
}(tasks)
|
||||
}
|
||||
|
||||
tw.currentPos = (tw.currentPos + 1) % tw.size
|
||||
}
|
||||
|
||||
func (tw *TimeWheel[K, V]) AddTask(delay int, task Task[K, V]) {
|
||||
if delay < 0 || delay >= tw.size {
|
||||
return
|
||||
}
|
||||
|
||||
tw.slotMutex.Lock()
|
||||
defer tw.slotMutex.Unlock()
|
||||
|
||||
pos := (tw.currentPos + delay) % tw.size
|
||||
tw.slots[pos] = append(tw.slots[pos], task)
|
||||
}
|
||||
Reference in New Issue
Block a user