Clash.Meta/common/observable/observable.go

66 lines
1.2 KiB
Go
Raw Normal View History

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