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  }