Exemplo n.º 1
0
        def subscribe(observer, scheduler=None):
            is_open = [False]

            def on_next(left):
                if is_open[0]:
                    observer.on_next(left)

            def on_completed():
                if is_open[0]:
                    observer.on_completed()

            subs = source.subscribe_(on_next, observer.on_error, on_completed,
                                     scheduler)
            subscriptions = CompositeDisposable(subs)

            right_subscription = SingleAssignmentDisposable()
            subscriptions.add(right_subscription)

            def on_next2(x):
                is_open[0] = True
                right_subscription.dispose()

            def on_completed2():
                right_subscription.dispose()

            right_subscription.disposable = other.subscribe_(
                on_next2, observer.on_error, on_completed2, scheduler)

            return subscriptions
Exemplo n.º 2
0
        def subscribe(observer, scheduler=None):
            group = CompositeDisposable()
            is_stopped = [False]
            m = SingleAssignmentDisposable()
            group.add(m)

            def on_next(inner_source):
                inner_subscription = SingleAssignmentDisposable()
                group.add(inner_subscription)

                inner_source = from_future(inner_source) if is_future(inner_source) else inner_source

                @synchronized(source.lock)
                def on_completed():
                    group.remove(inner_subscription)
                    if is_stopped[0] and len(group) == 1:
                        observer.on_completed()

                on_next = synchronized(source.lock)(observer.on_next)
                on_error = synchronized(source.lock)(observer.on_error)
                subscription = inner_source.subscribe_(on_next, on_error, on_completed, scheduler)
                inner_subscription.disposable = subscription

            def on_completed():
                is_stopped[0] = True
                if len(group) == 1:
                    observer.on_completed()

            m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler)
            return group
Exemplo n.º 3
0
def test_groupdisposable_clear():
    disp1 = [False]
    disp2 = [False]
    def action1():
        disp1[0] = True
    d1 = Disposable(action1)

    def action2():
        disp2[0] = True
    d2 = Disposable(action2)

    g = CompositeDisposable(d1, d2)
    assert g.length == 2

    g.clear()
    assert disp1[0]
    assert disp2[0]
    assert not g.length

    disp3 = [False]
    def action3():
        disp3[0] = True
    d3 = Disposable(action3)
    g.add(d3);
    assert not disp3[0]
    assert g.length == 1
Exemplo n.º 4
0
    def subscribe(observer, scheduler=None):
        window = [Subject()]
        d = CompositeDisposable()
        r = RefCountDisposable(d)

        observer.on_next(add_ref(window[0], r))

        def on_next_window(x):
            window[0].on_next(x)

        def on_error(err):
            window[0].on_error(err)
            observer.on_error(err)

        def on_completed():
            window[0].on_completed()
            observer.on_completed()

        d.add(source.subscribe_(on_next_window, on_error, on_completed, scheduler))

        def on_next_observer(w):
            window[0].on_completed()
            window[0] = Subject()
            observer.on_next(add_ref(window[0], r))

        d.add(window_boundaries.subscribe_(on_next_observer, on_error, on_completed, scheduler))
        return r
Exemplo n.º 5
0
Arquivo: do.py Projeto: wensincai/RxPY
        def subscribe(observer, scheduler=None):

            was_invoked = [False]

            def on_completed():
                observer.on_completed()
                try:
                    if not was_invoked[0]:
                        finally_action()
                        was_invoked[0] = True
                except Exception as err:  # pylint: disable=broad-except
                    observer.on_error(err)

            def on_error(exception):
                observer.on_error(exception)
                try:
                    if not was_invoked[0]:
                        finally_action()
                        was_invoked[0] = True
                except Exception as err:  # pylint: disable=broad-except
                    observer.on_error(err)

            composite_disposable = CompositeDisposable()
            composite_disposable.add(OnDispose(was_invoked))
            subscription = source.subscribe_(observer.on_next, on_error,
                                             on_completed, scheduler)
            composite_disposable.add(subscription)

            return composite_disposable
Exemplo n.º 6
0
    def run(self):
      srcs = list(self.parent.sources)

      N = len(srcs)

      self.queues = [None] * N
      self.isDone = [False] * N
      self.subscriptions = [None] * N
      self.gate = RLock()

      for i in range(0, N):
        self.queues[i] = deque()

      # Loop twice because subscribing could already yield
      # a value before all queues are initialized
      for i in range(0, N):
        d = SingleAssignmentDisposable()
        self.subscriptions[i] = d

        o = self.O(self, i)
        d.disposable = srcs[i].subscribeSafe(o)

      c = CompositeDisposable(self.subscriptions)

      def dispose():
        for q in self.queues:
          q.clear()

      c.add(Disposable.create(dispose))

      return c
Exemplo n.º 7
0
        def subscribe(observer, scheduler_=None):
            _scheduler = scheduler or scheduler_ or timeout_scheduler

            n = [0]
            s = [None]
            timer_d = SerialDisposable()
            window_id = [0]
            group_disposable = CompositeDisposable(timer_d)
            ref_count_disposable = RefCountDisposable(group_disposable)

            def create_timer(_id):
                m = SingleAssignmentDisposable()
                timer_d.disposable = m

                def action(scheduler, state):
                    if _id != window_id[0]:
                        return

                    n[0] = 0
                    window_id[0] += 1
                    new_id = window_id[0]
                    s[0].on_completed()
                    s[0] = Subject()
                    observer.on_next(add_ref(s[0], ref_count_disposable))
                    create_timer(new_id)

                m.disposable = _scheduler.schedule_relative(timespan, action)

            s[0] = Subject()
            observer.on_next(add_ref(s[0], ref_count_disposable))
            create_timer(0)

            def on_next(x):
                new_window = False
                new_id = 0

                s[0].on_next(x)
                n[0] += 1
                if n[0] == count:
                    new_window = True
                    n[0] = 0
                    window_id[0] += 1
                    new_id = window_id[0]
                    s[0].on_completed()
                    s[0] = Subject()
                    observer.on_next(add_ref(s[0], ref_count_disposable))

                if new_window:
                    create_timer(new_id)

            def on_error(e):
                s[0].on_error(e)
                observer.on_error(e)

            def on_completed():
                s[0].on_completed()
                observer.on_completed()

            group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_))
            return ref_count_disposable
Exemplo n.º 8
0
        def run(self):
            srcs = list(self.parent.sources)

            N = len(srcs)

            self.queues = [None] * N
            self.isDone = [False] * N
            self.subscriptions = [None] * N
            self.gate = RLock()

            for i in range(0, N):
                self.queues[i] = deque()

            # Loop twice because subscribing could already yield
            # a value before all queues are initialized
            for i in range(0, N):
                d = SingleAssignmentDisposable()
                self.subscriptions[i] = d

                o = self.O(self, i)
                d.disposable = srcs[i].subscribeSafe(o)

            c = CompositeDisposable(self.subscriptions)

            def dispose():
                for q in self.queues:
                    q.clear()

            c.add(Disposable.create(dispose))

            return c
Exemplo n.º 9
0
        def subscribe(observer, scheduler=None):
            group = CompositeDisposable()
            is_stopped = [False]
            m = SingleAssignmentDisposable()
            group.add(m)

            def on_next(inner_source):
                inner_subscription = SingleAssignmentDisposable()
                group.add(inner_subscription)

                inner_source = from_future(inner_source) if is_future(
                    inner_source) else inner_source

                @synchronized(source.lock)
                def on_completed():
                    group.remove(inner_subscription)
                    if is_stopped[0] and len(group) == 1:
                        observer.on_completed()

                on_next = synchronized(source.lock)(observer.on_next)
                on_error = synchronized(source.lock)(observer.on_error)
                subscription = inner_source.subscribe_(on_next, on_error,
                                                       on_completed, scheduler)
                inner_subscription.disposable = subscription

            def on_completed():
                is_stopped[0] = True
                if len(group) == 1:
                    observer.on_completed()

            m.disposable = source.subscribe_(on_next, observer.on_error,
                                             on_completed, scheduler)
            return group
Exemplo n.º 10
0
        def subscribe(observer, scheduler=None):
            window_subject = Subject()
            d = CompositeDisposable()
            r = RefCountDisposable(d)

            observer.on_next(add_ref(window_subject, r))

            def on_next_window(x):
                window_subject.on_next(x)

            def on_error(err):
                window_subject.on_error(err)
                observer.on_error(err)

            def on_completed():
                window_subject.on_completed()
                observer.on_completed()

            d.add(
                source.subscribe_(on_next_window, on_error, on_completed,
                                  scheduler))

            def on_next_observer(w):
                nonlocal window_subject
                window_subject.on_completed()
                window_subject = Subject()
                observer.on_next(add_ref(window_subject, r))

            d.add(
                boundaries.subscribe_(on_next_observer, on_error, on_completed,
                                      scheduler))
            return r
Exemplo n.º 11
0
    def _subscribe_core(self, observer=None, scheduler=None) -> typing.Disposable:
        clock = self.scheduler.to_seconds(self.scheduler.now)
        self.subscriptions.append(Subscription(clock))
        index = len(self.subscriptions) - 1
        disp = CompositeDisposable()

        def get_action(notification):
            def action(scheduler, state):
                notification.accept(observer)
                return Disposable()
            return action

        for message in self.messages:
            notification = message.value

            # Don't make closures within a loop
            action = get_action(notification)
            disp.add(self.scheduler.schedule_relative(message.time, action))

        def dispose() -> None:
            start = self.subscriptions[index].subscribe
            end = self.scheduler.to_seconds(self.scheduler.now)
            self.subscriptions[index] = Subscription(start, end)
            disp.dispose()

        return Disposable(dispose)
Exemplo n.º 12
0
        def subscribe(observer, scheduler=None):
            is_open = [False]

            def on_next(left):
                if is_open[0]:
                    observer.on_next(left)

            def on_completed():
                if is_open[0]:
                    observer.on_completed()

            subs = source.subscribe_(on_next, observer.on_error, on_completed, scheduler)
            subscriptions = CompositeDisposable(subs)

            right_subscription = SingleAssignmentDisposable()
            subscriptions.add(right_subscription)

            def on_next2(x):
                is_open[0] = True
                right_subscription.dispose()

            def on_completed2():
                right_subscription.dispose()

            right_subscription.disposable = other.subscribe_(on_next2, observer.on_error, on_completed2, scheduler)

            return subscriptions
Exemplo n.º 13
0
        def subscribe(observer, scheduler=None):

            was_invoked = [False]

            def on_completed():
                observer.on_completed()
                try:
                    if not was_invoked[0]:
                        finally_action()
                        was_invoked[0] = True
                except Exception as err:  # pylint: disable=broad-except
                    observer.on_error(err)

            def on_error(exception):
                observer.on_error(exception)
                try:
                    if not was_invoked[0]:
                        finally_action()
                        was_invoked[0] = True
                except Exception as err:  # pylint: disable=broad-except
                    observer.on_error(err)

            composite_disposable = CompositeDisposable()
            composite_disposable.add(OnDispose(was_invoked))
            subscription = source.subscribe_(observer.on_next, on_error, on_completed, scheduler)
            composite_disposable.add(subscription)

            return composite_disposable
        def subscribe(observer, scheduler_=None):
            _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()

            n = [0]
            s = [None]
            timer_d = SerialDisposable()
            window_id = [0]
            group_disposable = CompositeDisposable(timer_d)
            ref_count_disposable = RefCountDisposable(group_disposable)

            def create_timer(_id):
                m = SingleAssignmentDisposable()
                timer_d.disposable = m

                def action(scheduler, state):
                    if _id != window_id[0]:
                        return

                    n[0] = 0
                    window_id[0] += 1
                    new_id = window_id[0]
                    s[0].on_completed()
                    s[0] = Subject()
                    observer.on_next(add_ref(s[0], ref_count_disposable))
                    create_timer(new_id)

                m.disposable = _scheduler.schedule_relative(timespan, action)

            s[0] = Subject()
            observer.on_next(add_ref(s[0], ref_count_disposable))
            create_timer(0)

            def on_next(x):
                new_window = False
                new_id = 0

                s[0].on_next(x)
                n[0] += 1
                if n[0] == count:
                    new_window = True
                    n[0] = 0
                    window_id[0] += 1
                    new_id = window_id[0]
                    s[0].on_completed()
                    s[0] = Subject()
                    observer.on_next(add_ref(s[0], ref_count_disposable))

                if new_window:
                    create_timer(new_id)

            def on_error(e):
                s[0].on_error(e)
                observer.on_error(e)

            def on_completed():
                s[0].on_completed()
                observer.on_completed()

            group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_))
            return ref_count_disposable
Exemplo n.º 15
0
Arquivo: do.py Projeto: wensincai/RxPY
 def subscribe(observer, scheduler=None):
     composite_disposable = CompositeDisposable()
     composite_disposable.add(OnDispose())
     subscription = source.subscribe_(observer.on_next, observer.on_error,
                                      observer.on_completed, scheduler)
     composite_disposable.add(subscription)
     return composite_disposable
Exemplo n.º 16
0
def test_groupdisposable_clear():
    disp1 = [False]
    disp2 = [False]

    def action1():
        disp1[0] = True

    d1 = Disposable(action1)

    def action2():
        disp2[0] = True

    d2 = Disposable(action2)

    g = CompositeDisposable(d1, d2)
    assert g.length == 2

    g.clear()
    assert disp1[0]
    assert disp2[0]
    assert not g.length

    disp3 = [False]

    def action3():
        disp3[0] = True

    d3 = Disposable(action3)
    g.add(d3)
    assert not disp3[0]
    assert g.length == 1
Exemplo n.º 17
0
        def on_subscribe(observer, scheduler):
            def on_next(i):
                if type(i) is rs.OnNextMux:
                    observer.on_next(i._replace(key=i.key[1]))
                elif type(i) is rs.OnErrorMux:
                    observer.on_error(i.error)
                '''
                elif type(i) is rs.OnCreateMux:
                    observer.on_next(rs.OnCreateMux(i.key[1]))
                elif type(i) is rs.OnCompletedMux:
                    observer.on_next(rs.OnCompletedMux(i.key[1]))
                else:
                    observer.on_next(TypeError("flatten_aggregate: unknow item type: {}".format(type(i))))
                '''

            def on_next_outer(i):
                observer.on_next(i)

            disposable = CompositeDisposable()
            disposable.add(
                outer_group.subscribe(
                    on_next=on_next_outer,
                    scheduler=scheduler,
                ))
            disposable.add(
                source.subscribe(
                    on_next=on_next,
                    on_completed=observer.on_completed,
                    on_error=observer.on_error,
                    scheduler=scheduler,
                ))
            return disposable
Exemplo n.º 18
0
        def subscribe(observer, scheduler=None):
            accumulator_value = [seed]
            active = [False]
            group = CompositeDisposable()
            is_stopped = [False]
            queue = []

            def subscribe(xs):
                subscription = SingleAssignmentDisposable()
                group.add(subscription)

                @synchronized(source.lock)
                def on_next(next_accumulator_value):
                    accumulator_value[0] = next_accumulator_value
                    observer.on_next(next_accumulator_value)

                @synchronized(source.lock)
                def on_completed():
                    group.remove(subscription)
                    if queue:
                        s = queue.pop(0)
                        subscribe(s)
                    else:
                        active[0] = False
                        if is_stopped[0]:
                            observer.on_completed()

                on_error = synchronized(source.lock)(observer.on_error)
                subscription.disposable = xs.subscribe_(
                    on_next, on_error, on_completed, scheduler)

            def on_next(value):
                def accumulate():
                    has_accumulator_value = accumulator_value[0] is not NotSet
                    if has_accumulator_value:
                        acc_source = accumulator(accumulator_value[0], value)
                        return from_future(acc_source) if is_future(
                            acc_source) else acc_source
                    else:
                        return of(value)

                accumulator_source = defer(lambda _: accumulate())
                if not active[0]:
                    active[0] = True
                    subscribe(accumulator_source)
                else:
                    queue.append(accumulator_source)

            def on_completed():
                is_stopped[0] = True
                if not active[0]:
                    observer.on_completed()

            group.add(
                source.subscribe_(on_next, observer.on_error, on_completed,
                                  scheduler))
            return group
Exemplo n.º 19
0
def test_groupdisposable_add():
    d1 = Disposable()
    d2 = Disposable()

    g = CompositeDisposable(d1)

    assert g.length == 1
    assert g.contains(d1)
    g.add(d2)
    assert g.length == 2
    assert g.contains(d2)
Exemplo n.º 20
0
def test_groupdisposable_add():
    d1 = Disposable()
    d2 = Disposable()

    g = CompositeDisposable(d1)

    assert g.length == 1
    assert g.contains(d1)
    g.add(d2)
    assert g.length == 2
    assert g.contains(d2)
 def observe(self,
             observer_info: MultiCastObserverInfo) -> rx.typing.Disposable:
     composite_disposable = CompositeDisposable()
     disposable = self.source.observe(
         init_observer_info(observer=FromFlowableMultiCastObserver(
             next_observer=observer_info.observer,
             subscriber=self.subscriber,
             composite_disposable=composite_disposable,
         )))
     composite_disposable.add(disposable)
     return composite_disposable
Exemplo n.º 22
0
    def run(self):
      self.gate = RLock()

      groupDisposable = CompositeDisposable()
      self.refCountDisposable = RefCountDisposable(groupDisposable)

      self.createWindow()

      groupDisposable.add(self.parent.scheduler.schedulePeriodic(self.parent.timeSpan, self.tick))
      groupDisposable.add(self.parent.source.subscribeSafe(self))

      return self.refCountDisposable
    def observe(self, observer_info: ObserverInfo):
        composite_disposable = CompositeDisposable()

        disposable = self.source.observe(
            observer_info.copy(observer=FlatMergeNoBackpressureObserver(
                observer=observer_info.observer,
                selector=self.selector,
                scheduler=self.scheduler,
                subscribe_scheduler=self.subscribe_scheduler,
                composite_disposable=composite_disposable,
            ), ))
        composite_disposable.add(disposable)

        return composite_disposable
Exemplo n.º 24
0
        def run(self):
            self.gate = RLock()

            groupDisposable = CompositeDisposable()
            self.refCountDisposable = RefCountDisposable(groupDisposable)

            self.createWindow()

            groupDisposable.add(
                self.parent.scheduler.schedulePeriodic(self.parent.timeSpan,
                                                       self.tick))
            groupDisposable.add(self.parent.source.subscribeSafe(self))

            return self.refCountDisposable
Exemplo n.º 25
0
    def observe(self, observer_info: ObserverInfo):
        composite_disposable = CompositeDisposable()

        disposable = self.source.observe(
            observer_info.copy(observer=FlatMapObserver(
                observer_info=observer_info,
                func=self.func,
                scheduler=self.scheduler,
                subscribe_scheduler=self.subscribe_scheduler,
                composite_disposable=composite_disposable,
            )), )
        composite_disposable.add(disposable)

        return composite_disposable
Exemplo n.º 26
0
        def run(self):
            self.gate = RLock()
            self.s = Subject()
            self.n = 0
            self.windowId = 0

            self.timerDisposable = SerialDisposable()
            groupDisposable = CompositeDisposable(self.timerDisposable)
            self.refCountDisposable = RefCountDisposable(groupDisposable)

            # AddRef was originally WindowObservable but this is just an alias for AddRef
            self.observer.onNext(AddRef(self.s, self.refCountDisposable))
            self.createTimer(0)

            groupDisposable.add(self.parent.source.subscribeSafe(self))

            return self.refCountDisposable
Exemplo n.º 27
0
    def run(self):
      self.gate = RLock()
      self.s = Subject()
      self.n = 0
      self.windowId = 0

      self.timerDisposable = SerialDisposable()
      groupDisposable = CompositeDisposable(self.timerDisposable)
      self.refCountDisposable = RefCountDisposable(groupDisposable)

      # AddRef was originally WindowObservable but this is just an alias for AddRef
      self.observer.onNext(AddRef(self.s, self.refCountDisposable))
      self.createTimer(0)

      groupDisposable.add(self.parent.source.subscribeSafe(self))

      return self.refCountDisposable
Exemplo n.º 28
0
class RecursiveScheduledFunction(object):
  def __init__(self, action, scheduler, method = None):
    self.action = action
    self.group = CompositeDisposable()
    self.lock = RLock()

    if method == None:
      self.schedule = scheduler.scheduleWithState
    else:
      self.schedule = getattr(scheduler, method)

  def run(self, state):
    self.action(state, self.actionCallback)

  def actionCallback(self, newState, dueTime = None):
    self.isDone = False
    self.isAdded = False

    if dueTime == None:
      self.cancel = self.schedule(
        newState,
        self.schedulerCallback
      )
    else:
      self.cancel = self.schedule(
        newState,
        dueTime,
        self.schedulerCallback
      )

    with self.lock:
      if not self.isDone:
        self.group.add(self.cancel)
        self.isAdded = True

  def schedulerCallback(self, scheduler, state):
    with self.lock:
      if self.isAdded:
        self.group.remove(self.cancel)
      else:
        self.isDone = True

    self.run(state)

    return Disposable.empty()
Exemplo n.º 29
0
        def subscribe(observer, scheduler=None):
            m = SerialDisposable()
            d = CompositeDisposable(m)
            r = RefCountDisposable(d)
            window = Subject()

            observer.on_next(add_ref(window, r))

            def on_next(value):
                window.on_next(value)

            def on_error(error):
                window.on_error(error)
                observer.on_error(error)

            def on_completed():
                window.on_completed()
                observer.on_completed()

            d.add(source.subscribe_(on_next, on_error, on_completed,
                                    scheduler))

            def create_window_on_completed():
                try:
                    window_close = closing_mapper()
                except Exception as exception:
                    observer.on_error(exception)
                    return

                def on_completed():
                    nonlocal window
                    window.on_completed()
                    window = Subject()
                    observer.on_next(add_ref(window, r))
                    create_window_on_completed()

                m1 = SingleAssignmentDisposable()
                m.disposable = m1
                m1.disposable = window_close.pipe(ops.take(1)).subscribe_(
                    noop, on_error, on_completed, scheduler)

            create_window_on_completed()
            return r
Exemplo n.º 30
0
    def observe(self, observer_info: MultiCastObserverInfo) -> rx.typing.Disposable:
        group = CompositeDisposable()
        lock = threading.RLock()

        for inner_source in self.sources:
            inner_subscription = SingleAssignmentDisposable()
            group.add(inner_subscription)

            disposable = inner_source.observe(observer_info.copy(
                observer=MergeMultiCastObserver(
                    observer=observer_info.observer,
                    lock=lock,
                    inner_subscription=inner_subscription,
                    group=group
                )
            ))
            inner_subscription.disposable = disposable

        return group
Exemplo n.º 31
0
        def run(self):
            self.totalTime = 0
            self.nextShift = self.parent.timeShift
            self.nextSpan = self.parent.timeSpan

            self.gate = RLock()
            self.queue = deque()

            self.timerDisposable = SerialDisposable()

            groupDisposable = CompositeDisposable(self.timerDisposable)
            self.refCountDisposable = RefCountDisposable(groupDisposable)

            self.createWindow()
            self.createTimer()

            groupDisposable.add(self.parent.source.subscribeSafe(self))

            return self.refCountDisposable
Exemplo n.º 32
0
    def run(self):
      self.totalTime = 0
      self.nextShift = self.parent.timeShift
      self.nextSpan = self.parent.timeSpan

      self.gate = RLock()
      self.queue = deque()

      self.timerDisposable = SerialDisposable()

      groupDisposable = CompositeDisposable(self.timerDisposable)
      self.refCountDisposable = RefCountDisposable(groupDisposable)

      self.createWindow()
      self.createTimer()

      groupDisposable.add(self.parent.source.subscribeSafe(self))

      return self.refCountDisposable
Exemplo n.º 33
0
        def subscribe(observer, scheduler=None):
            active_count = [0]
            group = CompositeDisposable()
            is_stopped = [False]
            queue = []

            def subscribe(xs):
                subscription = SingleAssignmentDisposable()
                group.add(subscription)

                @synchronized(source.lock)
                def on_completed():
                    group.remove(subscription)
                    if queue:
                        s = queue.pop(0)
                        subscribe(s)
                    else:
                        active_count[0] -= 1
                        if is_stopped[0] and active_count[0] == 0:
                            observer.on_completed()

                on_next = synchronized(source.lock)(observer.on_next)
                on_error = synchronized(source.lock)(observer.on_error)
                subscription.disposable = xs.subscribe_(
                    on_next, on_error, on_completed, scheduler)

            def on_next(inner_source):
                if active_count[0] < max_concurrent:
                    active_count[0] += 1
                    subscribe(inner_source)
                else:
                    queue.append(inner_source)

            def on_completed():
                is_stopped[0] = True
                if active_count[0] == 0:
                    observer.on_completed()

            group.add(
                source.subscribe_(on_next, observer.on_error, on_completed,
                                  scheduler))
            return group
Exemplo n.º 34
0
    def subscribe(observer, scheduler=None):
        m = SerialDisposable()
        d = CompositeDisposable(m)
        r = RefCountDisposable(d)
        window = [Subject()]

        observer.on_next(add_ref(window[0], r))

        def on_next(value):
            window[0].on_next(value)

        def on_error(error):
            window[0].on_error(error)
            observer.on_error(error)

        def on_completed():
            window[0].on_completed()
            observer.on_completed()

        d.add(source.subscribe_(on_next, on_error, on_completed, scheduler))

        def create_window_on_completed():
            try:
                window_close = window_closing_mapper()
            except Exception as exception:
                observer.on_error(exception)
                return

            def on_completed():
                window[0].on_completed()
                window[0] = Subject()
                observer.on_next(add_ref(window[0], r))
                create_window_on_completed()

            m1 = SingleAssignmentDisposable()
            m.disposable = m1
            m1.disposable = window_close.pipe(ops.take(1)).subscribe_(noop, on_error, on_completed, scheduler)

        create_window_on_completed()
        return r
Exemplo n.º 35
0
        def subscribe(observer, scheduler=None):
            active_count = [0]
            group = CompositeDisposable()
            is_stopped = [False]
            queue = []

            def subscribe(xs):
                subscription = SingleAssignmentDisposable()
                group.add(subscription)

                @synchronized(source.lock)
                def on_completed():
                    group.remove(subscription)
                    if queue:
                        s = queue.pop(0)
                        subscribe(s)
                    else:
                        active_count[0] -= 1
                        if is_stopped[0] and active_count[0] == 0:
                            observer.on_completed()

                on_next = synchronized(source.lock)(observer.on_next)
                on_error = synchronized(source.lock)(observer.on_error)
                subscription.disposable = xs.subscribe_(on_next, on_error, on_completed, scheduler)

            def on_next(inner_source):
                if active_count[0] < max_concurrent:
                    active_count[0] += 1
                    subscribe(inner_source)
                else:
                    queue.append(inner_source)

            def on_completed():
                is_stopped[0] = True
                if active_count[0] == 0:
                    observer.on_completed()

            group.add(source.subscribe_(on_next, observer.on_error, on_completed, scheduler))
            return group
Exemplo n.º 36
0
def test_groupdisposable_addafterdispose():
    disp1 = [False]
    disp2 = [False]

    def action1():
        disp1[0] = True

    d1 = Disposable(action1)

    def action2():
        disp2[0] = True

    d2 = Disposable(action2)

    g = CompositeDisposable(d1)
    assert g.length == 1
    g.dispose()
    assert disp1[0]
    assert g.length == 0
    g.add(d2)
    assert disp2[0]
    assert g.length == 0
Exemplo n.º 37
0
class RecursiveScheduledFunction(object):
    def __init__(self, action, scheduler, method=None):
        self.action = action
        self.group = CompositeDisposable()
        self.lock = RLock()

        if method == None:
            self.schedule = scheduler.scheduleWithState
        else:
            self.schedule = getattr(scheduler, method)

    def run(self, state):
        self.action(state, self.actionCallback)

    def actionCallback(self, newState, dueTime=None):
        self.isDone = False
        self.isAdded = False

        if dueTime == None:
            self.cancel = self.schedule(newState, self.schedulerCallback)
        else:
            self.cancel = self.schedule(newState, dueTime,
                                        self.schedulerCallback)

        with self.lock:
            if not self.isDone:
                self.group.add(self.cancel)
                self.isAdded = True

    def schedulerCallback(self, scheduler, state):
        with self.lock:
            if self.isAdded:
                self.group.remove(self.cancel)
            else:
                self.isDone = True

        self.run(state)

        return Disposable.empty()
Exemplo n.º 38
0
def test_groupdisposable_addafterdispose():
    disp1 = [False]
    disp2 = [False]

    def action1():
        disp1[0] = True

    d1 = Disposable(action1)

    def action2():
        disp2[0] = True

    d2 = Disposable(action2)

    g = CompositeDisposable(d1)
    assert g.length == 1
    g.dispose()
    assert disp1[0]
    assert g.length == 0
    g.add(d2)
    assert disp2[0]
    assert g.length == 0
Exemplo n.º 39
0
        def subscribe(self, single: Single):
            group = CompositeDisposable()
            m = SingleAssignmentDisposable()
            group.add(m)
            lock = threading.RLock()

            class MergeAllSingle(Single):
                # def on_error(self, exc: Exception):
                #     single.on_error(exc)

                def on_next(_, inner_source: Ack):
                    class ResultSingle(Single):
                        def on_next(self, elem):
                            single.on_next(elem)

                        # def on_error(self, exc: Exception):
                        #     single.on_error(exc)

                    disposable = inner_source.subscribe(ResultSingle())
                    group.add(disposable)

            m.disposable = source.subscribe(MergeAllSingle())
            return group
Exemplo n.º 40
0
        def subscribe(observer, scheduler=None):
            has_current = [False]
            is_stopped = [False]
            m = SingleAssignmentDisposable()
            g = CompositeDisposable()

            g.add(m)

            def on_next(inner_source):
                if not has_current[0]:
                    has_current[0] = True

                    inner_source = rx.from_future(inner_source) if is_future(inner_source) else inner_source

                    inner_subscription = SingleAssignmentDisposable()
                    g.add(inner_subscription)

                    def on_completed_inner():
                        g.remove(inner_subscription)
                        has_current[0] = False
                        if is_stopped[0] and len(g) == 1:
                            observer.on_completed()

                    inner_subscription.disposable = inner_source.subscribe_(
                        observer.on_next,
                        observer.on_error,
                        on_completed_inner,
                        scheduler
                    )

            def on_completed():
                is_stopped[0] = True
                if not has_current[0] and len(g) == 1:
                    observer.on_completed()

            m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler)
            return g
Exemplo n.º 41
0
        def subscribe(observer, scheduler=None):
            has_current = [False]
            is_stopped = [False]
            m = SingleAssignmentDisposable()
            g = CompositeDisposable()

            g.add(m)

            def on_next(inner_source):
                if not has_current[0]:
                    has_current[0] = True

                    inner_source = rx.from_future(inner_source) if is_future(
                        inner_source) else inner_source

                    inner_subscription = SingleAssignmentDisposable()
                    g.add(inner_subscription)

                    def on_completed_inner():
                        g.remove(inner_subscription)
                        has_current[0] = False
                        if is_stopped[0] and len(g) == 1:
                            observer.on_completed()

                    inner_subscription.disposable = inner_source.subscribe_(
                        observer.on_next, observer.on_error,
                        on_completed_inner, scheduler)

            def on_completed():
                is_stopped[0] = True
                if not has_current[0] and len(g) == 1:
                    observer.on_completed()

            m.disposable = source.subscribe_(on_next, observer.on_error,
                                             on_completed, scheduler)
            return g
Exemplo n.º 42
0
class Bus(Generic[T], Closeable, ABC):
    def __init__(self, serial: Serial, scanner: BusScanner) -> None:
        super().__init__()

        self.__serial = serial
        self.__scanner = scanner
        self.__added_devices: Subject[Device[T]] = Subject()
        self.__device_list: List[Device[T]] = list()

        self.__disposable = CompositeDisposable()
        self.__disposable.add(self.__added_devices)

        self.__disposable.add(self.__scanner.scan().subscribe(
            on_next=self.__add_device,
            on_error=self.close,
            scheduler=NewThreadScheduler()))

    def __add_device(self, device: Device[T]) -> None:

        assert device not in self.__device_list

        self.__device_list.append(device)
        self.__added_devices.on_next(device)

        self.__disposable.add(device.on_close().subscribe(
            lambda _: self.__remove_device(device)))

    def __remove_device(self, device: Device[T]) -> None:
        self.__device_list.remove(device)

    def close(self, reason: str = None) -> None:
        super().close(reason)

        self.__disposable.dispose()

        for device in self.__device_list:
            device.close(reason)

    def get_devices(self) -> Observable:

        return rx.concat(rx.from_list(self.__device_list),
                         self.__added_devices)

    @property
    def serial(self) -> Serial:
        return self.__serial
Exemplo n.º 43
0
        def subscribe(observer, scheduler=None):
            group = CompositeDisposable()
            left_done = [False]
            left_map = OrderedDict()
            left_id = [0]
            right_done = [False]
            right_map = OrderedDict()
            right_id = [0]

            def on_next_left(value):
                duration = None
                current_id = left_id[0]
                left_id[0] += 1
                md = SingleAssignmentDisposable()

                left_map[current_id] = value
                group.add(md)

                def expire():
                    if current_id in left_map:
                        del left_map[current_id]
                    if not len(left_map) and left_done[0]:
                        observer.on_completed()

                    return group.remove(md)

                try:
                    duration = left_duration_mapper(value)
                except Exception as exception:
                    observer.on_error(exception)
                    return

                md.disposable = duration.pipe(take(1)).subscribe_(noop, observer.on_error, lambda: expire(), scheduler)

                for val in right_map.values():
                    result = (value, val)
                    observer.on_next(result)

            def on_completed_left():
                left_done[0] = True
                if right_done[0] or not len(left_map):
                    observer.on_completed()

            group.add(left.subscribe_(on_next_left, observer.on_error, on_completed_left, scheduler))

            def on_next_right(value):
                duration = None
                current_id = right_id[0]
                right_id[0] += 1
                md = SingleAssignmentDisposable()
                right_map[current_id] = value
                group.add(md)

                def expire():
                    if current_id in right_map:
                        del right_map[current_id]
                    if not len(right_map) and right_done[0]:
                        observer.on_completed()

                    return group.remove(md)

                try:
                    duration = right_duration_mapper(value)
                except Exception as exception:
                    observer.on_error(exception)
                    return

                md.disposable = duration.pipe(take(1)).subscribe_(noop, observer.on_error, lambda: expire(), scheduler)

                for val in left_map.values():
                    result = (val, value)
                    observer.on_next(result)

            def on_completed_right():
                right_done[0] = True
                if left_done[0] or not len(right_map):
                    observer.on_completed()

            group.add(right.subscribe_(on_next_right, observer.on_error, on_completed_right))
            return group
Exemplo n.º 44
0
class GroupBy(Producer):
  def __init__(self, source, keySelector, elementSelector):
    self.source = source
    self.keySelector = keySelector
    self.elementSelector = elementSelector

  def run(self, observer, cancel, setSink):
    self.groupDisposable = CompositeDisposable()
    self.refCountDisposable = RefCountDisposable(self.groupDisposable)

    sink = self.Sink(self, observer, cancel)
    setSink(sink)
    self.groupDisposable.add(self.source.subscribeSafe(sink))

    return self.refCountDisposable


  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(GroupBy.Sink, self).__init__(observer, cancel)
      self.parent = parent
      self.map = {}
      self.null = None

    def onNext(self, value):
      key = None

      try:
        key = self.parent.keySelector(value)
      except Exception as e:
        self.onError(e)
        return

      fireNewMapEntry = False
      writer = None

      try:
        if key == None:
          if self.null == None:
            self.null = Subject()
            fireNewMapEntry = True

          writer = self.null
        else:
          if key in self.map:
            writer = self.map[key]
          else:
            writer = Subject()
            self.map[key] = writer
            fireNewMapEntry = True
      except Exception as e:
        self.onError(e)
        return

      if fireNewMapEntry:
        group = GroupObservable(key, writer, self.parent.refCountDisposable)
        self.observer.onNext(group)

      element = None

      try:
        element = self.parent.elementSelector(value)
      except Exception as e:
        self.onError(e)
      else:
        writer.onNext(element)

    def onError(self, exception):
      if self.null != None:
        self.null.onError(exception)

      for x in self.map.values():
        x.onError(exception)

      self.observer.onError(exception)
      self.dispose()

    def onCompleted(self):
      if self.null != None:
        self.null.onCompleted()

      for x in self.map.values():
        x.onCompleted()

      self.observer.onCompleted()
      self.dispose()
Exemplo n.º 45
0
class GroupBy(Producer):
    def __init__(self, source, keySelector, elementSelector):
        self.source = source
        self.keySelector = keySelector
        self.elementSelector = elementSelector

    def run(self, observer, cancel, setSink):
        self.groupDisposable = CompositeDisposable()
        self.refCountDisposable = RefCountDisposable(self.groupDisposable)

        sink = self.Sink(self, observer, cancel)
        setSink(sink)
        self.groupDisposable.add(self.source.subscribeSafe(sink))

        return self.refCountDisposable

    class Sink(rx.linq.sink.Sink):
        def __init__(self, parent, observer, cancel):
            super(GroupBy.Sink, self).__init__(observer, cancel)
            self.parent = parent
            self.map = {}
            self.null = None

        def onNext(self, value):
            key = None

            try:
                key = self.parent.keySelector(value)
            except Exception as e:
                self.onError(e)
                return

            fireNewMapEntry = False
            writer = None

            try:
                if key == None:
                    if self.null == None:
                        self.null = Subject()
                        fireNewMapEntry = True

                    writer = self.null
                else:
                    if key in self.map:
                        writer = self.map[key]
                    else:
                        writer = Subject()
                        self.map[key] = writer
                        fireNewMapEntry = True
            except Exception as e:
                self.onError(e)
                return

            if fireNewMapEntry:
                group = GroupObservable(key, writer,
                                        self.parent.refCountDisposable)
                self.observer.onNext(group)

            element = None

            try:
                element = self.parent.elementSelector(value)
            except Exception as e:
                self.onError(e)
            else:
                writer.onNext(element)

        def onError(self, exception):
            if self.null != None:
                self.null.onError(exception)

            for x in self.map.values():
                x.onError(exception)

            self.observer.onError(exception)
            self.dispose()

        def onCompleted(self):
            if self.null != None:
                self.null.onCompleted()

            for x in self.map.values():
                x.onCompleted()

            self.observer.onCompleted()
            self.dispose()
Exemplo n.º 46
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(DelayObservable.Sink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.delays = CompositeDisposable()
      self.gate = RLock()
      self.atEnd = False
      self.subscription = SerialDisposable()

      if self.parent.subscriptionDelay == None:
        self.start()
      else:
        self.subscription.disposable = self.parent.subscriptionDelay.subscribeSafe(self.Sigma(self))

      return CompositeDisposable(self.subscription, self.delays)

    def start(self):
      self.subscription.disposable = self.parent.source.subscribeSafe(self)

    def onNext(self, value):
      try:
        delay = self.parent.delaySelector(value)
      except Exception as e:
        with self.gate:
          self.observer.onError(e)
          self.dispose()
      else:
        d = SingleAssignmentDisposable()
        self.delays.add(d)
        d.disposable = delay.subscribeSafe(self.Delta(self, value, d))

    def onError(self, exception):
      with self.gate:
        self.observer.onError(exception)
        self.dispose()

    def onCompleted(self):
      with self.gate:
        self.atEnd = True
        self.subscription.dispose()

        self.checkDone()

    def checkDone(self):
      if self.atEnd and self.delays.length == 0:
        self.observer.onCompleted()
        self.dispose()

    class Sigma(Observer):
      def __init__(self, parent):
        self.parent = parent

      def onNext(self, value):
        self.parent.start()

      def onError(self, exception):
        self.parent.observer.onError(exception)
        self.parent.dispose()

      def onCompleted(self):
        self.parent.start()

    class Delta(Observer):
      def __init__(self, parent, value, cancelSelf):
        self.parent = parent
        self.value = value
        self.cancelSelf = cancelSelf

      def onNext(self, delay):
        with self.parent.gate:
          self.parent.observer.onNext(self.value)
          self.parent.delays.remove(self.cancelSelf)
          self.parent.checkDone()

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        with self.parent.gate:
          self.parent.observer.onNext(self.value)
          self.parent.delays.remove(self.cancelSelf)
          self.parent.checkDone()
Exemplo n.º 47
0
        def subscribe(observer, scheduler=None):
            group = CompositeDisposable()
            rcd = RefCountDisposable(group)
            left_map = OrderedDict()
            right_map = OrderedDict()
            left_id = [0]
            right_id = [0]

            def on_next_left(value):
                subject = Subject()

                with left.lock:
                    _id = left_id[0]
                    left_id[0] += 1
                    left_map[_id] = subject

                try:
                    result = (value, add_ref(subject, rcd))
                except Exception as e:
                    log.error("*** Exception: %s" % e)
                    for left_value in left_map.values():
                        left_value.on_error(e)

                    observer.on_error(e)
                    return

                observer.on_next(result)

                for right_value in right_map.values():
                    subject.on_next(right_value)

                md = SingleAssignmentDisposable()
                group.add(md)

                def expire():
                    if _id in left_map:
                        del left_map[_id]
                        subject.on_completed()

                    group.remove(md)

                try:
                    duration = left_duration_mapper(value)
                except Exception as e:
                    for left_value in left_map.values():
                        left_value.on_error(e)

                    observer.on_error(e)
                    return

                def on_error(error):
                    for left_value in left_map.values():
                        left_value.on_error(error)

                    observer.on_error(error)

                md.disposable = duration.pipe(ops.take(1)).subscribe_(nothing, on_error, expire, scheduler)

            def on_error_left(error):
                for left_value in left_map.values():
                    left_value.on_error(error)

                observer.on_error(error)

            group.add(left.subscribe_(on_next_left, on_error_left, observer.on_completed, scheduler))

            def send_right(value):
                with left.lock:
                    _id = right_id[0]
                    right_id[0] += 1
                    right_map[_id] = value

                md = SingleAssignmentDisposable()
                group.add(md)

                def expire():
                    del right_map[_id]
                    group.remove(md)

                try:
                    duration = right_duration_mapper(value)
                except Exception as e:
                    for left_value in left_map.values():
                        left_value.on_error(e)

                    observer.on_error(e)
                    return

                def on_error(error):
                    with left.lock:
                        for left_value in left_map.values():
                            left_value.on_error(error)

                        observer.on_error(error)

                md.disposable = duration.pipe(ops.take(1)).subscribe_(nothing, on_error, expire, scheduler)

                with left.lock:
                    for left_value in left_map.values():
                        left_value.on_next(value)

            def on_error_right(error):
                for left_value in left_map.values():
                    left_value.on_error(error)

                observer.on_error(error)

            group.add(right.subscribe_(send_right, on_error_right, scheduler=scheduler))
            return rcd
Exemplo n.º 48
0
        def subscribe(observer, scheduler=None):
            writers = OrderedDict()
            group_disposable = CompositeDisposable()
            ref_count_disposable = RefCountDisposable(group_disposable)

            def on_next(x):
                writer = None
                key = None

                try:
                    key = key_mapper(x)
                except Exception as e:
                    for wrt in writers.values():
                        wrt.on_error(e)

                    observer.on_error(e)
                    return

                fire_new_map_entry = False
                writer = writers.get(key)
                if not writer:
                    writer = Subject()
                    writers[key] = writer
                    fire_new_map_entry = True

                if fire_new_map_entry:
                    group = GroupedObservable(key, writer, ref_count_disposable)
                    duration_group = GroupedObservable(key, writer)
                    try:
                        duration = duration_mapper(duration_group)
                    except Exception as e:
                        for wrt in writers.values():
                            wrt.on_error(e)

                        observer.on_error(e)
                        return

                    observer.on_next(group)
                    sad = SingleAssignmentDisposable()
                    group_disposable.add(sad)

                    def expire():
                        if writers[key]:
                            del writers[key]
                            writer.on_completed()

                        group_disposable.remove(sad)

                    def on_next(value):
                        pass

                    def on_error(exn):
                        for wrt in writers.values():
                            wrt.on_error(exn)
                        observer.on_error(exn)

                    def on_completed():
                        expire()

                    sad.disposable = duration.pipe(ops.take(1)).subscribe_(on_next, on_error, on_completed, scheduler)

                try:
                    element = element_mapper(x)
                except Exception as error:
                    for wrt in writers.values():
                        wrt.on_error(error)

                    observer.on_error(error)
                    return

                writer.on_next(element)

            def on_error(ex):
                for wrt in writers.values():
                    wrt.on_error(ex)

                observer.on_error(ex)

            def on_completed():
                for wrt in writers.values():
                    wrt.on_completed()

                observer.on_completed()

            group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler))
            return ref_count_disposable
Exemplo n.º 49
0
        def subscribe(observer, scheduler_=None):
            _scheduler = scheduler or scheduler_ or timeout_scheduler

            timer_d = SerialDisposable()
            next_shift = [timeshift]
            next_span = [timespan]
            total_time = [DELTA_ZERO]
            q = []

            group_disposable = CompositeDisposable(timer_d)
            ref_count_disposable = RefCountDisposable(group_disposable)

            def create_timer():
                m = SingleAssignmentDisposable()
                timer_d.disposable = m
                is_span = False
                is_shift = False

                if next_span[0] == next_shift[0]:
                    is_span = True
                    is_shift = True
                elif next_span[0] < next_shift[0]:
                    is_span = True
                else:
                    is_shift = True

                new_total_time = next_span[0] if is_span else next_shift[0]

                ts = new_total_time - total_time[0]
                total_time[0] = new_total_time
                if is_span:
                    next_span[0] += timeshift

                if is_shift:
                    next_shift[0] += timeshift

                def action(scheduler, state=None):
                    s = None

                    if is_shift:
                        s = Subject()
                        q.append(s)
                        observer.on_next(add_ref(s, ref_count_disposable))

                    if is_span:
                        s = q.pop(0)
                        s.on_completed()

                    create_timer()

                m.disposable = _scheduler.schedule_relative(ts, action)

            q.append(Subject())
            observer.on_next(add_ref(q[0], ref_count_disposable))
            create_timer()

            def on_next(x):
                for s in q:
                    s.on_next(x)

            def on_error(e):
                for s in q:
                    s.on_error(e)

                observer.on_error(e)

            def on_completed():
                for s in q:
                    s.on_completed()

                observer.on_completed()

            group_disposable.add(
                source.subscribe_(on_next, on_error, on_completed, scheduler_))
            return ref_count_disposable
Exemplo n.º 50
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(GroupJoin.Sink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.group = CompositeDisposable()
      self.refCount = RefCountDisposable(self.group)

      leftSubscription = SingleAssignmentDisposable()
      self.group.add(leftSubscription)
      self.leftID = 0
      self.leftMap = {}

      rightSubscription = SingleAssignmentDisposable()
      self.group.add(rightSubscription)
      self.rightID = 0
      self.rightMap = {}

      leftSubscription.disposable = self.parent.left.subscribeSafe(self.Left(self, leftSubscription))
      rightSubscription.disposable = self.parent.right.subscribeSafe(self.Right(self, rightSubscription))

      return self.refCount

    class Left(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def expire(self, resourceId, group, resource):
        with self.parent.gate:
          if resourceId in self.parent.leftMap:
            del self.parent.leftMap[resourceId]
            group.onCompleted()

        self.parent.group.remove(resource)

      def onNext(self, value):
        s = Subject()
        resourceId = 0

        with self.parent.gate:
          self.parent.leftID += 1
          resourceId = self.parent.leftID
          self.parent.leftMap[resourceId] = s

        # AddRef was originally WindowObservable but this is just an alias for AddRef
        window = AddRef(s, self.parent.refCount)
        md = SingleAssignmentDisposable()
        self.parent.group.add(md)

        try:
          duration = self.parent.parent.leftDurationSelector(value)
        except Exception as e:
          self.onError(e)
          return
        else:
          md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, s, md))

        try:
          result = self.parent.parent.resultSelector(value, window)
        except Exception as e:
          self.onError(e)
          return
        else:
          with self.parent.gate:
            self.parent.observer.onNext(result)

            for rightValue in self.parent.rightMap.values():
              s.onNext(rightValue)

      def onError(self, exception):
        with self.parent.gate:
          for o in self.parent.leftMap.values():
            o.onError(exception)

          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        with self.parent.gate:
          self.parent.observer.onCompleted()
          self.parent.dispose()

        self.dispose()


      class Delta(Observer):
        """Expires parent on Next or Completed"""

        def __init__(self, parent, resourceId, group, resource):
          self.parent = parent
          self.resourceId = resourceId
          self.group = group
          self.resource = resource

        def onNext(self, value):
          self.parent.expire(self.resourceId, self.group, self.resource)

        def onError(self, exception):
          self.parent.onError(exception)

        def onCompleted(self):
          self.parent.expire(self.resourceId, self.group, self.resource)
      #end Delta
    #end Left

    class Right(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription


      def expire(self, resourceId, resource):
        with self.parent.gate:
          self.parent.rightMap.pop(resourceId, None)

        self.parent.group.remove(resource)

      def onNext(self, value):
        resourceId = 0

        with self.parent.gate:
          self.parent.rightID += 1
          resourceId = self.parent.rightID
          self.parent.rightMap[resourceId] = value

        md = SingleAssignmentDisposable()
        self.parent.group.add(md)

        try:
          duration = self.parent.parent.rightDurationSelector(value)
        except Exception as e:
          self.onError(e)
          return
        else:
          md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md))

        with self.parent.gate:
          for o in self.parent.leftMap.values():
            o.onNext(value)

      def onError(self, exception):
        with self.parent.gate:
          for o in self.parent.leftMap.values():
            o.onError(exception)

          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        self.dispose()


      class Delta(Observer):
        """Expires parent on Next or Completed"""
        def __init__(self, parent, resourceId, resource):
          self.parent = parent
          self.resourceId = resourceId
          self.resource = resource

        def onNext(self, value):
          self.parent.expire(self.resourceId, self.resource)

        def onError(self, exception):
          self.parent.onError(exception)

        def onCompleted(self):
          self.parent.expire(self.resourceId, self.resource)
Exemplo n.º 51
0
        def subscribe(observer, scheduler=None):
            group = CompositeDisposable()
            left_done = False
            left_map = OrderedDict()
            left_id = 0
            right_done = False
            right_map = OrderedDict()
            right_id = 0

            def on_next_left(value):
                nonlocal left_id
                duration = None
                current_id = left_id
                left_id += 1
                md = SingleAssignmentDisposable()

                left_map[current_id] = value
                group.add(md)

                def expire():
                    if current_id in left_map:
                        del left_map[current_id]
                    if not len(left_map) and left_done:
                        observer.on_completed()

                    return group.remove(md)

                try:
                    duration = left_duration_mapper(value)
                except Exception as exception:
                    observer.on_error(exception)
                    return

                md.disposable = duration.pipe(take(1)).subscribe_(
                    noop, observer.on_error, lambda: expire(), scheduler)

                for val in right_map.values():
                    result = (value, val)
                    observer.on_next(result)

            def on_completed_left():
                nonlocal left_done
                left_done = True
                if right_done or not len(left_map):
                    observer.on_completed()

            group.add(
                left.subscribe_(on_next_left, observer.on_error,
                                on_completed_left, scheduler))

            def on_next_right(value):
                nonlocal right_id
                duration = None
                current_id = right_id
                right_id += 1
                md = SingleAssignmentDisposable()
                right_map[current_id] = value
                group.add(md)

                def expire():
                    if current_id in right_map:
                        del right_map[current_id]
                    if not len(right_map) and right_done:
                        observer.on_completed()

                    return group.remove(md)

                try:
                    duration = right_duration_mapper(value)
                except Exception as exception:
                    observer.on_error(exception)
                    return

                md.disposable = duration.pipe(take(1)).subscribe_(
                    noop, observer.on_error, lambda: expire(), scheduler)

                for val in left_map.values():
                    result = (val, value)
                    observer.on_next(result)

            def on_completed_right():
                nonlocal right_done
                right_done = True
                if left_done or not len(right_map):
                    observer.on_completed()

            group.add(
                right.subscribe_(on_next_right, observer.on_error,
                                 on_completed_right, scheduler))
            return group
Exemplo n.º 52
0
class GroupByUntil(Producer):
  def __init__(self, source, keySelector, elementSelector, durationSelector):
    self.source = source
    self.keySelector = keySelector
    self.elementSelector = elementSelector
    self.durationSelector = durationSelector

  def run(self, observer, cancel, setSink):
    self.groupDisposable = CompositeDisposable()
    self.refCountDisposable = RefCountDisposable(self.groupDisposable)

    sink = self.Sink(self, observer, cancel)
    setSink(sink)
    self.groupDisposable.add(self.source.subscribeSafe(sink))

    return self.refCountDisposable


  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(GroupByUntil.Sink, self).__init__(observer, cancel)
      self.parent = parent
      self.map = {}
      self.null = None
      self.nullGate = RLock()
      self.nullGateForDeltas = RLock()
      self.observerGate = RLock()
      self.writerGate = RLock()

    def onNext(self, value):
      key = None

      try:
        key = self.parent.keySelector(value)
      except Exception as e:
        self.onError(e)
        return

      fireNewMapEntry = False
      writer = None

      try:
        if key == None:
          with self.nullGate:
            if self.null == None:
              self.null = Subject()
              fireNewMapEntry = True

            writer = self.null
        else:
          if key in self.map:
            writer = self.map[key]
          else:
            writer = Subject()
            self.map[key] = writer
            fireNewMapEntry = True
      except Exception as e:
        self.onError(e)
        return

      if fireNewMapEntry:
        group = GroupObservable(key, writer, self.parent.refCountDisposable)

        duration = None
        durationGroup = GroupObservable(key, writer)

        try:
          duration = self.parent.durationSelector(durationGroup)
        except Exception as e:
          self.onError(e)
          return

        with self.observerGate:
          self.observer.onNext(group)

        md = SingleAssignmentDisposable()
        self.parent.groupDisposable.add(md)
        md.disposable = duration.subscribeSafe(self.Delta(self, key, writer, md))

      element = None

      try:
        element = self.parent.elementSelector(value)
      except Exception as e:
        self.onError(e)
      else:
        with self.writerGate:
          writer.onNext(element)

    def onError(self, exception):
      #
      # NOTE: A race with OnCompleted triggered by a duration selector is fine when
      #       using Subject<T>. It will transition into a terminal state, making one
      #       of the two calls a no-op by swapping in a DoneObserver<T>.
      #
      null = None

      with self.nullGate:
        null = self.null

      if null != None:
        null.onError(exception)

      for x in self.map.values():
        x.onError(exception)

      with self.observerGate:
        self.observer.onError(exception)

      self.dispose()

    def onCompleted(self):
      #
      # NOTE: A race with OnCompleted triggered by a duration selector is fine when
      #       using Subject<T>. It will transition into a terminal state, making one
      #       of the two calls a no-op by swapping in a DoneObserver<T>.
      #
      null = None

      with self.nullGate:
        null = self.null

      if null != None:
        null.onCompleted()

      for x in self.map.values():
        x.onCompleted()

      with self.observerGate:
        self.observer.onCompleted()

      self.dispose()


    class Delta(Observer):
      def __init__(self, parent, key, writer, cancelSelf):
        self.parent = parent
        self.key = key
        self.writer = writer
        self.cancelSelf = cancelSelf

      def onNext(self, value):
        self.onCompleted()

      def onError(self, exception):
        self.parent.onError(exception)
        self.cancelSelf.dispose()

      def onCompleted(self):
        if self.key == None:
          null = None

          with self.parent.nullGate:
            null = self.parent.null
            self.parent.null = None

          with self.parent.nullGateForDeltas:
            null.onCompleted()
        else:
          try:
            del self.parent.map[self.key]
          except KeyError:
            pass
          else:
            with self.parent.writerGate:
              self.writer.onCompleted()

        self.parent.parent.groupDisposable.remove(self.cancelSelf)
Exemplo n.º 53
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(SelectMany.Sink, self).__init__(observer, cancel)
      self.parent = parent
      self.index = -1

    def run(self):
      self.gate = RLock()
      self.isStopped = False
      self.group = CompositeDisposable()

      self.sourceSubscription = SingleAssignmentDisposable()
      self.group.add(self.sourceSubscription)
      self.sourceSubscription.disposable = self.parent.source.subscribeSafe(self)

      return self.group

    def onNext(self, value):
      inner = None

      try:
        if self.parent.withIndex:
          self.index += 1
          inner = self.parent.selectorOnNext(value, self.index)
        else:
          inner = self.parent.selectorOnNext(value)
      except Exception as e:
        with self.gate:
          self.observer.onError(e)
          self.dispose()

      if isinstance(inner, Observable):
        self.subscribeInner(inner)
        return

      # iterable
      try:
        for current in inner:
          self.observer.onNext(current)
      except Exception as e:
        self.observer.onError(e)
        self.dispose()

    def onError(self, exception):
      if self.parent.selectorOnError != None:
        try:
          inner = None

          if self.parent.withIndex:
            self.index += 1
            inner = self.parent.selectorOnError(exception, self.index)
          else:
            inner = self.parent.selectorOnError(exception)
        except Exception as e:
          with self.gate:
            self.observer.onError(e)
            self.dispose()
        else:
          self.subscribeInner(inner)
          self.final()
      else:
        with self.gate:
          self.observer.onError(exception)
          self.dispose()

    def onCompleted(self):
      if self.parent.selectorOnCompleted != None:
        try:
          inner = None

          if self.parent.withIndex:
            inner = self.parent.selectorOnCompleted(self.index)
          else:
            inner = self.parent.selectorOnCompleted()
        except Exception as e:
          with self.gate:
            self.observer.onError(e)
            self.dispose()
            return
        else:
          self.subscribeInner(inner)

      self.final()

    def final(self):
      self.isStopped = True

      if self.group.length == 1:
        #
        # Notice there can be a race between OnCompleted of the source and any
        # of the inner sequences, where both see _group.Count == 1, and one is
        # waiting for the lock. There won't be a double OnCompleted observation
        # though, because the call to Dispose silences the observer by swapping
        # in a NopObserver<T>.
        #
        with self.gate:
          self.observer.onCompleted()
          self.dispose()
      else:
        self.sourceSubscription.dispose()

    def subscribeInner(self, inner):
      innerSubscription = SingleAssignmentDisposable()
      self.group.add(innerSubscription)
      innerSubscription.disposable = inner.subscribeSafe(self.LockingObserver(self, innerSubscription))

    class LockingObserver(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def onNext(self, value):
        with self.parent.gate:
          self.parent.observer.onNext(value)

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        self.parent.group.remove(self.subscription)

        if self.parent.isStopped and self.parent.group.length == 1:
          #
          # Notice there can be a race between OnCompleted of the source and any
          # of the inner sequences, where both see _group.Count == 1, and one is
          # waiting for the lock. There won't be a double OnCompleted observation
          # though, because the call to Dispose silences the observer by swapping
          # in a NopObserver<T>.
          #
          with self.parent.gate:
            self.parent.observer.onCompleted()
            self.parent.dispose()
Exemplo n.º 54
0
 def subscribe(observer, scheduler=None):
     composite_disposable = CompositeDisposable()
     composite_disposable.add(OnDispose())
     subscription = source.subscribe_(observer.on_next, observer.on_error, observer.on_completed, scheduler)
     composite_disposable.add(subscription)
     return composite_disposable
Exemplo n.º 55
0
        def subscribe(observer, scheduler_=None):
            _scheduler = scheduler or scheduler_ or timeout_scheduler

            timer_d = SerialDisposable()
            next_shift = [timeshift]
            next_span = [timespan]
            total_time = [DELTA_ZERO]
            q = []

            group_disposable = CompositeDisposable(timer_d)
            ref_count_disposable = RefCountDisposable(group_disposable)

            def create_timer():
                m = SingleAssignmentDisposable()
                timer_d.disposable = m
                is_span = False
                is_shift = False

                if next_span[0] == next_shift[0]:
                    is_span = True
                    is_shift = True
                elif next_span[0] < next_shift[0]:
                    is_span = True
                else:
                    is_shift = True

                new_total_time = next_span[0] if is_span else next_shift[0]

                ts = new_total_time - total_time[0]
                total_time[0] = new_total_time
                if is_span:
                    next_span[0] += timeshift

                if is_shift:
                    next_shift[0] += timeshift

                def action(scheduler, state=None):
                    s = None

                    if is_shift:
                        s = Subject()
                        q.append(s)
                        observer.on_next(add_ref(s, ref_count_disposable))

                    if is_span:
                        s = q.pop(0)
                        s.on_completed()

                    create_timer()
                m.disposable = _scheduler.schedule_relative(ts, action)

            q.append(Subject())
            observer.on_next(add_ref(q[0], ref_count_disposable))
            create_timer()

            def on_next(x):
                for s in q:
                    s.on_next(x)

            def on_error(e):
                for s in q:
                    s.on_error(e)

                observer.on_error(e)

            def on_completed():
                for s in q:
                    s.on_completed()

                observer.on_completed()

            group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_))
            return ref_count_disposable
Exemplo n.º 56
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(Join.Sink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.group = CompositeDisposable()
      self.refCount = RefCountDisposable(self.group)

      leftSubscription = SingleAssignmentDisposable()
      self.group.add(leftSubscription)
      self.leftDone = False
      self.leftID = 0
      self.leftMap = {}

      rightSubscription = SingleAssignmentDisposable()
      self.group.add(rightSubscription)
      self.rightDone = False
      self.rightID = 0
      self.rightMap = {}

      leftSubscription.disposable = self.parent.left.subscribeSafe(self.Lambda(self, leftSubscription))
      rightSubscription.disposable = self.parent.right.subscribeSafe(self.Roh(self, rightSubscription))

      return self.refCount

    class Lambda(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def expire(self, resourceId, resource):
        with self.parent.gate:
          if resourceId in self.parent.leftMap:
            del self.parent.leftMap[resourceId]

            if len(self.parent.leftMap) == 0 and self.parent.leftDone:
              self.parent.observer.onCompleted()
              self.parent.dispose()

        self.parent.group.remove(resource)

      def onNext(self, value):
        resourceId = 0

        with self.parent.gate:
          self.parent.leftID += 1
          resourceId = self.parent.leftID
          self.parent.leftMap[resourceId] = value

        # AddRef was originally WindowObservable but this is just an alias for AddRef
        md = SingleAssignmentDisposable()
        self.parent.group.add(md)

        try:
          duration = self.parent.parent.leftDurationSelector(value)
        except Exception as e:
          self.parent.observer.onError(e)
          self.parent.dispose()
          return
        else:
          md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md))

        with self.parent.gate:
          for rightValue in self.parent.rightMap.values():
            try:
              result = self.parent.parent.resultSelector(value, rightValue)
            except Exception as e:
              self.parent.observer.onError(e)
              self.parent.dispose()
              return
            else:
              self.parent.observer.onNext(result)

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        with self.parent.gate:
          self.parent.leftDone = True

          if self.parent.rightDone or len(self.parent.leftMap) == 0:
            self.parent.observer.onCompleted()
            self.parent.dispose()
          else:
            self.dispose()


      class Delta(Observer):
        """Expires parent on Next or Completed"""

        def __init__(self, parent, resourceId, resource):
          self.parent = parent
          self.resourceId = resourceId
          self.resource = resource

        def onNext(self, value):
          self.parent.expire(self.resourceId, self.resource)

        def onError(self, exception):
          self.parent.onError(exception)

        def onCompleted(self):
          self.parent.expire(self.resourceId, self.resource)
      #end Delta
    #end Lambda

    class Roh(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def expire(self, resourceId, resource):
        with self.parent.gate:
          if resourceId in self.parent.rightMap:
            del self.parent.rightMap[resourceId]

            if len(self.parent.rightMap) == 0 and self.parent.rightDone:
              self.parent.observer.onCompleted()
              self.parent.dispose()

        self.parent.group.remove(resource)

      def onNext(self, value):
        resourceId = 0

        with self.parent.gate:
          self.parent.rightID += 1
          resourceId = self.parent.rightID
          self.parent.rightMap[resourceId] = value

        # AddRef was originally WindowObservable but this is just an alias for AddRef
        md = SingleAssignmentDisposable()
        self.parent.group.add(md)

        try:
          duration = self.parent.parent.rightDurationSelector(value)
        except Exception as e:
          self.parent.observer.onError(e)
          self.parent.dispose()
          return
        else:
          md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md))

        with self.parent.gate:
          for leftValue in self.parent.leftMap.values():
            try:
              result = self.parent.parent.resultSelector(leftValue, value)
            except Exception as e:
              self.parent.observer.onError(e)
              self.parent.dispose()
              return
            else:
              self.parent.observer.onNext(result)

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        with self.parent.gate:
          self.parent.rightDone = True

          if self.parent.leftDone or len(self.parent.rightMap) == 0:
            self.parent.observer.onCompleted()
            self.parent.dispose()
          else:
            self.dispose()


      class Delta(Observer):
        """Expires parent on Next or Completed"""

        def __init__(self, parent, resourceId, resource):
          self.parent = parent
          self.resourceId = resourceId
          self.resource = resource

        def onNext(self, value):
          self.parent.expire(self.resourceId, self.resource)

        def onError(self, exception):
          self.parent.onError(exception)

        def onCompleted(self):
          self.parent.expire(self.resourceId, self.resource)
    #end Roh
  #end Sink
#end Join
Exemplo n.º 57
0
    class Sink(rx.linq.sink.Sink):
        def __init__(self, parent, observer, cancel):
            super(Join.Sink, self).__init__(observer, cancel)
            self.parent = parent

        def run(self):
            self.gate = RLock()
            self.group = CompositeDisposable()
            self.refCount = RefCountDisposable(self.group)

            leftSubscription = SingleAssignmentDisposable()
            self.group.add(leftSubscription)
            self.leftDone = False
            self.leftID = 0
            self.leftMap = {}

            rightSubscription = SingleAssignmentDisposable()
            self.group.add(rightSubscription)
            self.rightDone = False
            self.rightID = 0
            self.rightMap = {}

            leftSubscription.disposable = self.parent.left.subscribeSafe(
                self.Lambda(self, leftSubscription))
            rightSubscription.disposable = self.parent.right.subscribeSafe(
                self.Roh(self, rightSubscription))

            return self.refCount

        class Lambda(Observer):
            def __init__(self, parent, subscription):
                self.parent = parent
                self.subscription = subscription

            def expire(self, resourceId, resource):
                with self.parent.gate:
                    if resourceId in self.parent.leftMap:
                        del self.parent.leftMap[resourceId]

                        if len(self.parent.leftMap
                               ) == 0 and self.parent.leftDone:
                            self.parent.observer.onCompleted()
                            self.parent.dispose()

                self.parent.group.remove(resource)

            def onNext(self, value):
                resourceId = 0

                with self.parent.gate:
                    self.parent.leftID += 1
                    resourceId = self.parent.leftID
                    self.parent.leftMap[resourceId] = value

                # AddRef was originally WindowObservable but this is just an alias for AddRef
                md = SingleAssignmentDisposable()
                self.parent.group.add(md)

                try:
                    duration = self.parent.parent.leftDurationSelector(value)
                except Exception as e:
                    self.parent.observer.onError(e)
                    self.parent.dispose()
                    return
                else:
                    md.disposable = duration.subscribeSafe(
                        self.Delta(self, resourceId, md))

                with self.parent.gate:
                    for rightValue in self.parent.rightMap.values():
                        try:
                            result = self.parent.parent.resultSelector(
                                value, rightValue)
                        except Exception as e:
                            self.parent.observer.onError(e)
                            self.parent.dispose()
                            return
                        else:
                            self.parent.observer.onNext(result)

            def onError(self, exception):
                with self.parent.gate:
                    self.parent.observer.onError(exception)
                    self.parent.dispose()

            def onCompleted(self):
                with self.parent.gate:
                    self.parent.leftDone = True

                    if self.parent.rightDone or len(self.parent.leftMap) == 0:
                        self.parent.observer.onCompleted()
                        self.parent.dispose()
                    else:
                        self.dispose()

            class Delta(Observer):
                """Expires parent on Next or Completed"""
                def __init__(self, parent, resourceId, resource):
                    self.parent = parent
                    self.resourceId = resourceId
                    self.resource = resource

                def onNext(self, value):
                    self.parent.expire(self.resourceId, self.resource)

                def onError(self, exception):
                    self.parent.onError(exception)

                def onCompleted(self):
                    self.parent.expire(self.resourceId, self.resource)

            #end Delta

        #end Lambda

        class Roh(Observer):
            def __init__(self, parent, subscription):
                self.parent = parent
                self.subscription = subscription

            def expire(self, resourceId, resource):
                with self.parent.gate:
                    if resourceId in self.parent.rightMap:
                        del self.parent.rightMap[resourceId]

                        if len(self.parent.rightMap
                               ) == 0 and self.parent.rightDone:
                            self.parent.observer.onCompleted()
                            self.parent.dispose()

                self.parent.group.remove(resource)

            def onNext(self, value):
                resourceId = 0

                with self.parent.gate:
                    self.parent.rightID += 1
                    resourceId = self.parent.rightID
                    self.parent.rightMap[resourceId] = value

                # AddRef was originally WindowObservable but this is just an alias for AddRef
                md = SingleAssignmentDisposable()
                self.parent.group.add(md)

                try:
                    duration = self.parent.parent.rightDurationSelector(value)
                except Exception as e:
                    self.parent.observer.onError(e)
                    self.parent.dispose()
                    return
                else:
                    md.disposable = duration.subscribeSafe(
                        self.Delta(self, resourceId, md))

                with self.parent.gate:
                    for leftValue in self.parent.leftMap.values():
                        try:
                            result = self.parent.parent.resultSelector(
                                leftValue, value)
                        except Exception as e:
                            self.parent.observer.onError(e)
                            self.parent.dispose()
                            return
                        else:
                            self.parent.observer.onNext(result)

            def onError(self, exception):
                with self.parent.gate:
                    self.parent.observer.onError(exception)
                    self.parent.dispose()

            def onCompleted(self):
                with self.parent.gate:
                    self.parent.rightDone = True

                    if self.parent.leftDone or len(self.parent.rightMap) == 0:
                        self.parent.observer.onCompleted()
                        self.parent.dispose()
                    else:
                        self.dispose()

            class Delta(Observer):
                """Expires parent on Next or Completed"""
                def __init__(self, parent, resourceId, resource):
                    self.parent = parent
                    self.resourceId = resourceId
                    self.resource = resource

                def onNext(self, value):
                    self.parent.expire(self.resourceId, self.resource)

                def onError(self, exception):
                    self.parent.onError(exception)

                def onCompleted(self):
                    self.parent.expire(self.resourceId, self.resource)

        #end Roh

    #end Sink


#end Join
Exemplo n.º 58
0
  class ConcurrentSink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(Merge.ConcurrentSink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.q = Queue()
      self.isStopped = False
      self.activeCount = 0

      self.group = CompositeDisposable()
      self.sourceSubscription = SingleAssignmentDisposable()
      self.group.add(self.sourceSubscription)
      self.sourceSubscription.disposable = self.parent.sources.subscribeSafe(self)

      return self.group

    def onNext(self, value):
      with self.gate:
        if self.activeCount < self.parent.maxConcurrency:
          self.activeCount += 1
          self.subscribe(value)
        else:
          self.q.put_nowait(value)

    def onError(self, exception):
      with self.gate:
        self.observer.onError(exception)
        self.dispose()

    def onCompleted(self):
      with self.gate:
        self.isStopped = True

        if self.activeCount == 0:
          self.observer.onCompleted()
          self.dispose()
        else:
          self.sourceSubscription.dispose()

    def subscribe(self, innerSource):
      subscription = SingleAssignmentDisposable()
      self.group.add(subscription)
      subscription.disposable = innerSource.subscribeSafe(self.LockObserver(self, subscription))

    class LockObserver(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def onNext(self, value):
        with self.parent.gate:
          self.parent.observer.onNext(value)

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        self.parent.group.remove(self.subscription)

        with self.parent.gate:
          if self.parent.q.qsize() > 0:
            s = self.q.get()
            self.parent.subscribe(s)
          else:
            self.parent.activeCount -= 1

            if self.parent.isStopped and self.parent.activeCount == 0:
              self.parent.observer.onCompleted()
              self.parent.dispose()
Exemplo n.º 59
0
  class SerialSink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(Merge.SerialSink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.isStopped = False
      self.group = CompositeDisposable()

      self.sourceSubscription = SingleAssignmentDisposable()
      self.group.add(self.sourceSubscription)
      self.sourceSubscription.disposable = self.parent.sources.subscribeSafe(self)

      return self.group

    def onNext(self, value):
      innerSubscription = SingleAssignmentDisposable()
      self.group.add(innerSubscription)
      innerSubscription.disposable = value.subscribeSafe(self.LockObserver(self, innerSubscription))

    def onError(self, exception):
      with self.gate:
        self.observer.onError(exception)
        self.dispose()

    def onCompleted(self):
      self.isStopped = True

      if self.group.length == 1:
        #
        # Notice there can be a race between OnCompleted of the source and any
        # of the inner sequences, where both see _group.Count == 1, and one is
        # waiting for the lock. There won't be a double OnCompleted observation
        # though, because the call to Dispose silences the observer by swapping
        # in a NopObserver<T>.
        #
        with self.gate:
          self.observer.onCompleted()
          self.dispose()
      else:
        self.sourceSubscription.dispose()

    class LockObserver(Observer):
      def __init__(self, parent, subscription):
        self.parent = parent
        self.subscription = subscription

      def onNext(self, value):
        with self.parent.gate:
          self.parent.observer.onNext(value)

      def onError(self, exception):
        with self.parent.gate:
          self.parent.observer.onError(exception)
          self.parent.dispose()

      def onCompleted(self):
        self.parent.group.remove(self.subscription)

        if self.parent.isStopped and self.parent.group.length == 1:
          #
          # Notice there can be a race between OnCompleted of the source and any
          # of the inner sequences, where both see _group.Count == 1, and one is
          # waiting for the lock. There won't be a double OnCompleted observation
          # though, because the call to Dispose silences the observer by swapping
          # in a NopObserver<T>.
          #
          with self.parent.gate:
            self.parent.observer.onCompleted()
            self.parent.dispose()