Skip to content

Commit

Permalink
Add pause manager
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Aug 7, 2023
1 parent a755de3 commit 4db0062
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
22 changes: 22 additions & 0 deletions service/pause/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package pause

import (
"context"

"github.com/sagernet/sing/service"
)

func ManagerFromContext(ctx context.Context) Manager {
return service.FromContext[Manager](ctx)
}

func ContextWithManager(ctx context.Context, manager Manager) context.Context {
return service.ContextWith[Manager](ctx, manager)
}

func ContextWithDefaultManager(ctx context.Context) context.Context {
if service.FromContext[Manager](ctx) != nil {
return ctx
}
return service.ContextWith[Manager](ctx, NewDefaultManager(ctx))
}
101 changes: 101 additions & 0 deletions service/pause/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package pause

import (
"context"
"sync"
)

type defaultManager struct {
ctx context.Context
access sync.Mutex
devicePause chan struct{}
networkPause chan struct{}
}

func NewDefaultManager(ctx context.Context) Manager {
devicePauseChan := make(chan struct{})
networkPauseChan := make(chan struct{})
close(devicePauseChan)
close(networkPauseChan)
return &defaultManager{
ctx: ctx,
devicePause: devicePauseChan,
networkPause: networkPauseChan,
}
}

func (d *defaultManager) DevicePause() {
d.access.Lock()
defer d.access.Unlock()
select {
case <-d.devicePause:
d.devicePause = make(chan struct{})
default:
}
}

func (d *defaultManager) DeviceWake() {
d.access.Lock()
defer d.access.Unlock()
select {
case <-d.devicePause:
default:
close(d.devicePause)
}
}

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.networkPause = make(chan struct{})
default:
}
}

func (d *defaultManager) NetworkWake() {
d.access.Lock()
defer d.access.Unlock()
select {
case <-d.networkPause:
default:
close(d.networkPause)
}
}

func (d *defaultManager) NetworkPauseChan() <-chan struct{} {
return d.networkPause
}

func (d *defaultManager) IsPaused() bool {
select {
case <-d.devicePause:
default:
return true
}

select {
case <-d.networkPause:
default:
return true
}

return false
}

func (d *defaultManager) WaitActive() {
select {
case <-d.devicePause:
case <-d.ctx.Done():
}

select {
case <-d.networkPause:
case <-d.ctx.Done():
}
}
12 changes: 12 additions & 0 deletions service/pause/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pause

type Manager interface {
DevicePause()
DeviceWake()
DevicePauseChan() <-chan struct{}
NetworkPause()
NetworkWake()
NetworkPauseChan() <-chan struct{}
IsPaused() bool
WaitActive()
}

0 comments on commit 4db0062

Please sign in to comment.