diff options
| author | historia <[not public]> | 2026-06-09 05:59:20 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-09 05:59:20 -0400 |
| commit | 9eb5ab1818b6b19501fd7209db1987c9e06cc919 (patch) | |
| tree | 76e046b0bf611dfe939a8c8f6507467de2e9e20f /internal/engine | |
| download | thehouseoficarus-9eb5ab1818b6b19501fd7209db1987c9e06cc919.tar.gz | |
first commit
Diffstat (limited to 'internal/engine')
| -rw-r--r-- | internal/engine/tick.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/internal/engine/tick.go b/internal/engine/tick.go new file mode 100644 index 0000000..d6d470a --- /dev/null +++ b/internal/engine/tick.go @@ -0,0 +1,105 @@ +package engine + +import ( + "sync" + "time" +) + +const TickDuration = 600 * time.Millisecond + +type Callback func() bool + +type subscriber struct { + id uint64 + interval int + callback Callback + ticks int +} + +type Engine struct { + mu sync.Mutex + subscribers map[uint64]*subscriber + nextID uint64 + ticker *time.Ticker + running bool + stopCh chan struct{} +} + +func New() *Engine { + return &Engine{ + subscribers: make(map[uint64]*subscriber), + } +} + +func (e *Engine) Subscribe(interval int, cb Callback) uint64 { + e.mu.Lock() + defer e.mu.Unlock() + e.nextID++ + e.subscribers[e.nextID] = &subscriber{ + id: e.nextID, + interval: interval, + callback: cb, + } + return e.nextID +} + +func (e *Engine) Unsubscribe(id uint64) { + e.mu.Lock() + defer e.mu.Unlock() + delete(e.subscribers, id) +} + +func (e *Engine) Start() { + e.mu.Lock() + defer e.mu.Unlock() + if e.running { + return + } + e.running = true + e.ticker = time.NewTicker(TickDuration) + e.stopCh = make(chan struct{}) + + go func() { + for { + select { + case <-e.ticker.C: + e.processTick() + case <-e.stopCh: + return + } + } + }() +} + +func (e *Engine) Stop() { + e.mu.Lock() + defer e.mu.Unlock() + if e.ticker != nil { + e.ticker.Stop() + } + e.running = false + if e.stopCh != nil { + close(e.stopCh) + } +} + +func (e *Engine) processTick() { + e.mu.Lock() + snapshot := make(map[uint64]*subscriber, len(e.subscribers)) + for id, sub := range e.subscribers { + snapshot[id] = sub + } + e.mu.Unlock() + + for id, sub := range snapshot { + sub.ticks++ + if sub.ticks >= sub.interval { + sub.ticks = 0 + if !sub.callback() { + e.mu.Lock() + delete(e.subscribers, id) + e.mu.Unlock() + } + } + } +} |
