1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-11-09 00:14:57 +00:00
arikawa/internal/handleloop/handleloop.go
diamondburned 81b1a0a902 Session: Added a handleloop abstraction
This abstraction will mainly be in charge of handling events from a
channel and dispatching them to handlers in a thread safe manner. It
boxes synchronizing mechanisms inside a struct.
2020-11-17 12:15:05 -08:00

61 lines
1.2 KiB
Go

// Package handleloop provides clean abstractions to handle listening to
// channels and passing them onto event handlers.
package handleloop
import "github.com/diamondburned/arikawa/v2/utils/handler"
// Loop provides a reusable event looper abstraction. It is thread-safe to use
// concurrently.
type Loop struct {
dst *handler.Handler
run chan struct{}
stop chan struct{}
}
func NewLoop(dst *handler.Handler) *Loop {
return &Loop{
dst: dst,
run: make(chan struct{}, 1), // intentional 1 buffer
stop: make(chan struct{}), // intentional unbuffer
}
}
// Start starts a new event loop. It will try to stop existing loops before.
func (l *Loop) Start(src <-chan interface{}) {
// Ensure we're stopped.
l.Stop()
// Mark that we're running.
l.run <- struct{}{}
go func() {
for {
select {
case event := <-src:
l.dst.Call(event)
case <-l.stop:
l.stop <- struct{}{}
return
}
}
}()
}
// Stop tries to stop the Loop. If the Loop is not running, then it does
// nothing; thus, it can be called multiple times.
func (l *Loop) Stop() {
// Ensure that we are running before stopping.
select {
case <-l.run:
// running
default:
return
}
// send a close request
l.stop <- struct{}{}
// wait for a reply
<-l.stop
}