github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/observable/observer.go (about)

     1  package observable
     2  
     3  import (
     4  	"os"
     5  	"sync"
     6  )
     7  
     8  type Observable[T any] interface {
     9  	Subscribe() (subscription Subscription[T], done <-chan struct{}, err error)
    10  	UnSubscribe(subscription Subscription[T])
    11  }
    12  
    13  type Observer[T any] struct {
    14  	subscriber   *Subscriber[T]
    15  	listenerSize int
    16  	listener     map[Subscription[T]]*Subscriber[T]
    17  	mux          sync.Mutex
    18  	done         bool
    19  }
    20  
    21  func NewObserver[T any](subscriber *Subscriber[T], listenerBufferSize int) *Observer[T] {
    22  	observable := &Observer[T]{
    23  		subscriber:   subscriber,
    24  		listener:     map[Subscription[T]]*Subscriber[T]{},
    25  		listenerSize: listenerBufferSize,
    26  	}
    27  	go observable.process()
    28  	return observable
    29  }
    30  
    31  func (o *Observer[T]) process() {
    32  	subscription, done := o.subscriber.Subscription()
    33  process:
    34  	for {
    35  		select {
    36  		case <-done:
    37  			break process
    38  		case entry := <-subscription:
    39  			o.mux.Lock()
    40  			for _, sub := range o.listener {
    41  				sub.Emit(entry)
    42  			}
    43  			o.mux.Unlock()
    44  		}
    45  	}
    46  	o.mux.Lock()
    47  	defer o.mux.Unlock()
    48  	for _, listener := range o.listener {
    49  		listener.Close()
    50  	}
    51  }
    52  
    53  func (o *Observer[T]) Subscribe() (subscription Subscription[T], done <-chan struct{}, err error) {
    54  	o.mux.Lock()
    55  	defer o.mux.Unlock()
    56  	if o.done {
    57  		return nil, nil, os.ErrClosed
    58  	}
    59  	subscriber := NewSubscriber[T](o.listenerSize)
    60  	subscription, done = subscriber.Subscription()
    61  	o.listener[subscription] = subscriber
    62  	return
    63  }
    64  
    65  func (o *Observer[T]) UnSubscribe(subscription Subscription[T]) {
    66  	o.mux.Lock()
    67  	defer o.mux.Unlock()
    68  	subscriber, exist := o.listener[subscription]
    69  	if !exist {
    70  		return
    71  	}
    72  	delete(o.listener, subscription)
    73  	subscriber.Close()
    74  }
    75  
    76  func (o *Observer[T]) Emit(item T) {
    77  	o.subscriber.Emit(item)
    78  }
    79  
    80  func (o *Observer[T]) Close() error {
    81  	o.mux.Lock()
    82  	defer o.mux.Unlock()
    83  	if o.done {
    84  		return os.ErrClosed
    85  	}
    86  	o.subscriber.Close()
    87  	o.done = true
    88  	return nil
    89  }