github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/service/pause/default.go (about) 1 package pause 2 3 import ( 4 "context" 5 "sync" 6 7 "github.com/sagernet/sing/common/atomic" 8 "github.com/sagernet/sing/common/x/list" 9 "github.com/sagernet/sing/service" 10 ) 11 12 type defaultManager struct { 13 ctx context.Context 14 access sync.Mutex 15 devicePause chan struct{} 16 devicePaused atomic.Bool 17 networkPause chan struct{} 18 networkPaused atomic.Bool 19 callbacks list.List[Callback] 20 } 21 22 func WithDefaultManager(ctx context.Context) context.Context { 23 if service.FromContext[Manager](ctx) != nil { 24 return ctx 25 } 26 devicePauseChan := make(chan struct{}) 27 networkPauseChan := make(chan struct{}) 28 close(devicePauseChan) 29 close(networkPauseChan) 30 manager := &defaultManager{ 31 ctx: ctx, 32 devicePause: devicePauseChan, 33 networkPause: networkPauseChan, 34 } 35 return service.ContextWith[Manager](ctx, manager) 36 } 37 38 func (d *defaultManager) DevicePause() { 39 d.access.Lock() 40 defer d.access.Unlock() 41 select { 42 case <-d.devicePause: 43 d.devicePaused.Store(true) 44 d.devicePause = make(chan struct{}) 45 d.emit(EventDevicePaused) 46 default: 47 } 48 } 49 50 func (d *defaultManager) DeviceWake() { 51 d.access.Lock() 52 defer d.access.Unlock() 53 select { 54 case <-d.devicePause: 55 default: 56 d.devicePaused.Store(false) 57 close(d.devicePause) 58 d.emit(EventDeviceWake) 59 } 60 } 61 62 func (d *defaultManager) NetworkPause() { 63 d.access.Lock() 64 defer d.access.Unlock() 65 select { 66 case <-d.networkPause: 67 d.networkPaused.Store(true) 68 d.networkPause = make(chan struct{}) 69 d.emit(EventNetworkPause) 70 default: 71 } 72 } 73 74 func (d *defaultManager) NetworkWake() { 75 d.access.Lock() 76 defer d.access.Unlock() 77 select { 78 case <-d.networkPause: 79 default: 80 d.networkPaused.Store(false) 81 close(d.networkPause) 82 d.emit(EventNetworkWake) 83 } 84 } 85 86 func (d *defaultManager) RegisterCallback(callback Callback) *list.Element[Callback] { 87 d.access.Lock() 88 defer d.access.Unlock() 89 return d.callbacks.PushBack(callback) 90 } 91 92 func (d *defaultManager) UnregisterCallback(element *list.Element[Callback]) { 93 d.access.Lock() 94 defer d.access.Unlock() 95 d.callbacks.Remove(element) 96 } 97 98 func (d *defaultManager) IsDevicePaused() bool { 99 return d.devicePaused.Load() 100 } 101 102 func (d *defaultManager) IsNetworkPaused() bool { 103 return d.networkPaused.Load() 104 } 105 106 func (d *defaultManager) IsPaused() bool { 107 select { 108 case <-d.devicePause: 109 default: 110 return true 111 } 112 113 select { 114 case <-d.networkPause: 115 default: 116 return true 117 } 118 119 return false 120 } 121 122 func (d *defaultManager) WaitActive() { 123 select { 124 case <-d.devicePause: 125 case <-d.ctx.Done(): 126 } 127 128 select { 129 case <-d.networkPause: 130 case <-d.ctx.Done(): 131 } 132 } 133 134 func (d *defaultManager) emit(event int) { 135 for element := d.callbacks.Front(); element != nil; element = element.Next() { 136 element.Value(event) 137 } 138 }