Skip to content

Commit 4db0062

Browse files
committed
Add pause manager
1 parent a755de3 commit 4db0062

3 files changed

Lines changed: 135 additions & 0 deletions

File tree

service/pause/context.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package pause
2+
3+
import (
4+
"context"
5+
6+
"github.com/sagernet/sing/service"
7+
)
8+
9+
func ManagerFromContext(ctx context.Context) Manager {
10+
return service.FromContext[Manager](ctx)
11+
}
12+
13+
func ContextWithManager(ctx context.Context, manager Manager) context.Context {
14+
return service.ContextWith[Manager](ctx, manager)
15+
}
16+
17+
func ContextWithDefaultManager(ctx context.Context) context.Context {
18+
if service.FromContext[Manager](ctx) != nil {
19+
return ctx
20+
}
21+
return service.ContextWith[Manager](ctx, NewDefaultManager(ctx))
22+
}

service/pause/default.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package pause
2+
3+
import (
4+
"context"
5+
"sync"
6+
)
7+
8+
type defaultManager struct {
9+
ctx context.Context
10+
access sync.Mutex
11+
devicePause chan struct{}
12+
networkPause chan struct{}
13+
}
14+
15+
func NewDefaultManager(ctx context.Context) Manager {
16+
devicePauseChan := make(chan struct{})
17+
networkPauseChan := make(chan struct{})
18+
close(devicePauseChan)
19+
close(networkPauseChan)
20+
return &defaultManager{
21+
ctx: ctx,
22+
devicePause: devicePauseChan,
23+
networkPause: networkPauseChan,
24+
}
25+
}
26+
27+
func (d *defaultManager) DevicePause() {
28+
d.access.Lock()
29+
defer d.access.Unlock()
30+
select {
31+
case <-d.devicePause:
32+
d.devicePause = make(chan struct{})
33+
default:
34+
}
35+
}
36+
37+
func (d *defaultManager) DeviceWake() {
38+
d.access.Lock()
39+
defer d.access.Unlock()
40+
select {
41+
case <-d.devicePause:
42+
default:
43+
close(d.devicePause)
44+
}
45+
}
46+
47+
func (d *defaultManager) DevicePauseChan() <-chan struct{} {
48+
return d.devicePause
49+
}
50+
51+
func (d *defaultManager) NetworkPause() {
52+
d.access.Lock()
53+
defer d.access.Unlock()
54+
select {
55+
case <-d.networkPause:
56+
d.networkPause = make(chan struct{})
57+
default:
58+
}
59+
}
60+
61+
func (d *defaultManager) NetworkWake() {
62+
d.access.Lock()
63+
defer d.access.Unlock()
64+
select {
65+
case <-d.networkPause:
66+
default:
67+
close(d.networkPause)
68+
}
69+
}
70+
71+
func (d *defaultManager) NetworkPauseChan() <-chan struct{} {
72+
return d.networkPause
73+
}
74+
75+
func (d *defaultManager) IsPaused() bool {
76+
select {
77+
case <-d.devicePause:
78+
default:
79+
return true
80+
}
81+
82+
select {
83+
case <-d.networkPause:
84+
default:
85+
return true
86+
}
87+
88+
return false
89+
}
90+
91+
func (d *defaultManager) WaitActive() {
92+
select {
93+
case <-d.devicePause:
94+
case <-d.ctx.Done():
95+
}
96+
97+
select {
98+
case <-d.networkPause:
99+
case <-d.ctx.Done():
100+
}
101+
}

service/pause/manager.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package pause
2+
3+
type Manager interface {
4+
DevicePause()
5+
DeviceWake()
6+
DevicePauseChan() <-chan struct{}
7+
NetworkPause()
8+
NetworkWake()
9+
NetworkPauseChan() <-chan struct{}
10+
IsPaused() bool
11+
WaitActive()
12+
}

0 commit comments

Comments
 (0)