github.com/igoogolx/clash@v1.19.8/common/observable/observable.go (about) 1 package observable 2 3 import ( 4 "errors" 5 "sync" 6 ) 7 8 type Observable struct { 9 iterable Iterable 10 listener map[Subscription]*Subscriber 11 mux sync.Mutex 12 done bool 13 } 14 15 func (o *Observable) 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) 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) Subscribe() (Subscription, 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() 43 o.listener[subscriber.Out()] = subscriber 44 return subscriber.Out(), nil 45 } 46 47 func (o *Observable) UnSubscribe(sub Subscription) { 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(any Iterable) *Observable { 59 observable := &Observable{ 60 iterable: any, 61 listener: map[Subscription]*Subscriber{}, 62 } 63 go observable.process() 64 return observable 65 }