Improve pause manager

This commit is contained in:
世界 2023-12-15 01:09:36 +08:00
parent 81d1bc2768
commit cdb9908442
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 57 additions and 12 deletions

View file

@ -3,13 +3,19 @@ package pause
import (
"context"
"sync"
"github.com/sagernet/sing/common/atomic"
"github.com/sagernet/sing/common/x/list"
)
type defaultManager struct {
ctx context.Context
access sync.Mutex
devicePause chan struct{}
devicePaused atomic.Bool
networkPause chan struct{}
networkPaused atomic.Bool
callbacks list.List[Callback]
}
func NewDefaultManager(ctx context.Context) Manager {
@ -29,7 +35,9 @@ func (d *defaultManager) DevicePause() {
defer d.access.Unlock()
select {
case <-d.devicePause:
d.devicePaused.Store(true)
d.devicePause = make(chan struct{})
d.emit(EventDevicePaused)
default:
}
}
@ -40,20 +48,20 @@ func (d *defaultManager) DeviceWake() {
select {
case <-d.devicePause:
default:
d.devicePaused.Store(false)
close(d.devicePause)
d.emit(EventDeviceWake)
}
}
func (d *defaultManager) DevicePauseChan() <-chan struct{} {
return d.devicePause
}
func (d *defaultManager) NetworkPause() {
d.access.Lock()
defer d.access.Unlock()
select {
case <-d.networkPause:
d.networkPaused.Store(true)
d.networkPause = make(chan struct{})
d.emit(EventNetworkPause)
default:
}
}
@ -64,12 +72,30 @@ func (d *defaultManager) NetworkWake() {
select {
case <-d.networkPause:
default:
d.networkPaused.Store(false)
close(d.networkPause)
d.emit(EventNetworkWake)
}
}
func (d *defaultManager) NetworkPauseChan() <-chan struct{} {
return d.networkPause
func (d *defaultManager) RegisterCallback(callback Callback) *list.Element[Callback] {
d.access.Lock()
defer d.access.Unlock()
return d.callbacks.PushBack(callback)
}
func (d *defaultManager) UnregisterCallback(element *list.Element[Callback]) {
d.access.Lock()
defer d.access.Unlock()
d.callbacks.Remove(element)
}
func (d *defaultManager) IsDevicePaused() bool {
return d.devicePaused.Load()
}
func (d *defaultManager) IsNetworkPaused() bool {
return d.networkPaused.Load()
}
func (d *defaultManager) IsPaused() bool {
@ -99,3 +125,9 @@ func (d *defaultManager) WaitActive() {
case <-d.ctx.Done():
}
}
func (d *defaultManager) emit(event int) {
for element := d.callbacks.Front(); element != nil; element = element.Next() {
element.Value(event)
}
}

View file

@ -1,12 +1,25 @@
package pause
import "github.com/sagernet/sing/common/x/list"
type Manager interface {
DevicePause()
DeviceWake()
DevicePauseChan() <-chan struct{}
NetworkPause()
NetworkWake()
NetworkPauseChan() <-chan struct{}
IsDevicePaused() bool
IsNetworkPaused() bool
IsPaused() bool
WaitActive()
RegisterCallback(callback Callback) *list.Element[Callback]
UnregisterCallback(element *list.Element[Callback])
}
const (
EventDevicePaused int = iota
EventDeviceWake
EventNetworkPause
EventNetworkWake
)
type Callback = func(event int)