95 lines
1.7 KiB
Go
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()
|
|
}()
|
|
}
|