github.com/metacubex/mihomo@v1.18.5/common/observable/observable.go (about) 1 package observable 2 3 import ( 4 "errors" 5 "sync" 6 ) 7 8 type Observable[T any] struct { 9 iterable Iterable[T] 10 listener map[Subscription[T]]*Subscriber[T] 11 mux sync.Mutex 12 done bool 13 } 14 15 func (o *Observable[T]) process() { 16 for item := range o.iterable { 17 o.mux.Lock() 18 for _, sub := range o.listener { 19 sub.Emit(item) 20 } 21 o.mux.Unlock() 22 } 23 o.close() 24 } 25 26 func (o *Observable[T]) close() { 27 o.mux.Lock() 28 defer o.mux.Unlock() 29 30 o.done = true 31 for _, sub := range o.listener { 32 sub.Close() 33 } 34 } 35 36 func (o *Observable[T]) Subscribe() (Subscription[T], error) { 37 o.mux.Lock() 38 defer o.mux.Unlock() 39 if o.done { 40 return nil, errors.New("observable is closed") 41 } 42 subscriber := newSubscriber[T]() 43 o.listener[subscriber.Out()] = subscriber 44 return subscriber.Out(), nil 45 } 46 47 func (o *Observable[T]) UnSubscribe(sub Subscription[T]) { 48 o.mux.Lock() 49 defer o.mux.Unlock() 50 subscriber, exist := o.listener[sub] 51 if !exist { 52 return 53 } 54 delete(o.listener, sub) 55 subscriber.Close() 56 } 57 58 func NewObservable[T any](iter Iterable[T]) *Observable[T] { 59 observable := &Observable[T]{ 60 iterable: iter, 61 listener: map[Subscription[T]]*Subscriber[T]{}, 62 } 63 go observable.process() 64 return observable 65 }