clash/common/observable/observable.go

66 lines
1.1 KiB
Go
Raw Normal View History

2018-06-10 14:50:03 +00:00
package observable
import (
"errors"
"sync"
)
type Observable struct {
iterable Iterable
listener map[Subscription]*Subscriber
mux sync.Mutex
2018-06-10 14:50:03 +00:00
done bool
}
func (o *Observable) process() {
for item := range o.iterable {
o.mux.Lock()
for _, sub := range o.listener {
sub.Emit(item)
}
o.mux.Unlock()
2018-06-10 14:50:03 +00:00
}
o.close()
}
func (o *Observable) close() {
o.mux.Lock()
defer o.mux.Unlock()
2018-06-10 14:50:03 +00:00
o.done = true
for _, sub := range o.listener {
sub.Close()
}
2018-06-10 14:50:03 +00:00
}
func (o *Observable) Subscribe() (Subscription, error) {
o.mux.Lock()
defer o.mux.Unlock()
if o.done {
2018-06-10 14:50:03 +00:00
return nil, errors.New("Observable is closed")
}
subscriber := newSubscriber()
o.listener[subscriber.Out()] = subscriber
2018-06-10 14:50:03 +00:00
return subscriber.Out(), nil
}
func (o *Observable) UnSubscribe(sub Subscription) {
o.mux.Lock()
defer o.mux.Unlock()
subscriber, exist := o.listener[sub]
2018-06-10 14:50:03 +00:00
if !exist {
return
}
delete(o.listener, sub)
2018-06-10 14:50:03 +00:00
subscriber.Close()
}
func NewObservable(any Iterable) *Observable {
observable := &Observable{
iterable: any,
listener: map[Subscription]*Subscriber{},
2018-06-10 14:50:03 +00:00
}
go observable.process()
return observable
}