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() }() }