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