2025-09-30 12:47:59 +02:00

95 lines
1.7 KiB
Go

package interval
import (
"errors"
"math/rand"
"sync"
"time"
)
type MutexMap[K comparable, V any] struct {
mutex sync.Mutex
m map[K]V
}
func (m *MutexMap[K, V]) Get(key K) (V, error) {
m.mutex.Lock()
defer m.mutex.Unlock()
v, ok := m.m[key]
if !ok {
return v, errors.New("unknown key")
}
return v, nil
}
func (m *MutexMap[K, V]) Set(key K, value V) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.m[key] = value
}
func (m *MutexMap[K, V]) Delete(key K) {
m.mutex.Lock()
defer m.mutex.Unlock()
delete(m.m, key)
}
var stopChannels = MutexMap[int, chan bool]{
m: make(map[int]chan bool),
}
// SetInterval schedules a repeating task to be executed at a specified interval.
func SetInterval(f func(), milliseconds int) (id int) {
for {
id = rand.Int()
if _, err := stopChannels.Get(id); err == nil {
continue // ID collision, keep looking for another unique random value
}
break
}
stop := make(chan bool)
stopChannels.Set(id, stop)
ticker := time.NewTicker(time.Duration(milliseconds) * time.Millisecond)
go func() {
for {
select {
case <-stop:
ticker.Stop()
return
case <-ticker.C:
f()
}
}
}()
return
}
// ClearInterval stops a scheduled interval identified by the specified interval ID.
func ClearInterval(id int) error {
stop, err := stopChannels.Get(id)
if err != nil {
return err
}
stop <- true
stopChannels.Delete(id)
return nil
}
// SetTimeout schedules a one-time task to be executed after a specified interval.
func SetTimeout(f func(), milliseconds int) {
timer := time.NewTimer(time.Duration(milliseconds) * time.Millisecond)
go func() {
<-timer.C
timer.Stop()
f()
}()
}