mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-04-05 18:49:40 +02:00
91 lines
1.8 KiB
Go
91 lines
1.8 KiB
Go
package util
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
"errors"
|
|
)
|
|
|
|
type Signal struct {
|
|
isSet bool
|
|
autoReset bool
|
|
*sync.Mutex
|
|
chNotSet chan interface{} // channel is open, when signal isn't set
|
|
}
|
|
|
|
func NewSignal(isSet, autoReset bool) (s *Signal) {
|
|
s = &Signal{
|
|
Mutex: &sync.Mutex{},
|
|
isSet: isSet,
|
|
autoReset: autoReset,
|
|
chNotSet: make(chan interface{}, 0),
|
|
}
|
|
if s.isSet {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
s.isSet = true
|
|
close(s.chNotSet)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Signal) Set() {
|
|
// if signaled, the channel has to be closed
|
|
// we can't test if the channel is already closed (without waiting with select), so we keep track of the state
|
|
// in isSet, to avoid closing multiple times
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
if s.isSet {
|
|
return
|
|
}
|
|
s.isSet = true
|
|
close(s.chNotSet)
|
|
return
|
|
}
|
|
|
|
func (s *Signal) Reset() {
|
|
// in reset state, the channel has to exist, but mustn't be recreated if already existing (already in unset state)
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
if s.isSet {
|
|
// channel shouldn't exist
|
|
s.chNotSet = make(chan interface{}, 0)
|
|
s.isSet = false
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s Signal) IsSet() bool {
|
|
return s.isSet
|
|
}
|
|
|
|
func (s *Signal) Wait() {
|
|
select {
|
|
case <-s.chNotSet: // when channel isn't closed, this blocks
|
|
// if autoReset, recreate channel (setting signal to off)
|
|
if s.autoReset {
|
|
s.Lock()
|
|
s.chNotSet = make(chan interface{}, 0)
|
|
s.isSet = false
|
|
s.Unlock()
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Signal) WaitTimeout(timeout time.Duration) error {
|
|
select {
|
|
case <-s.chNotSet: // when channel isn't closed, this blocks
|
|
// if autoReset, recreate channel (setting signal to off)
|
|
if s.autoReset {
|
|
s.Lock()
|
|
s.chNotSet = make(chan interface{}, 0)
|
|
s.isSet = false
|
|
s.Unlock()
|
|
}
|
|
return nil
|
|
case <-time.After(timeout):
|
|
return errors.New("Timeout reached")
|
|
}
|
|
}
|