Example #1
0
    class EnumeratingSink(Observer):
        def __init__(self, onNext, done):
            self.onNextAction = onNext
            self.doneAction = done

            self.index = 0
            self.stopped = Atomic(False)
            self.exception = None

        def onNext(self, value):
            if not self.stopped.value:
                try:
                    self.onNextAction(value, self.index)
                    self.index += 1
                except Exception as e:
                    self.onError(e)

        def onError(self, exception):
            if not self.stopped.exchange(True):
                self.exception = exception
                self.doneAction()

        def onCompleted(self):
            if not self.stopped.exchange(True):
                self.doneAction()
Example #2
0
  class EnumeratingSink(Observer):
    def __init__(self, onNext, done):
      self.onNextAction = onNext
      self.doneAction = done

      self.index = 0
      self.stopped = Atomic(False)
      self.exception = None

    def onNext(self, value):
      if not self.stopped.value:
        try:
          self.onNextAction(value, self.index)
          self.index += 1
        except Exception as e:
          self.onError(e)

    def onError(self, exception):
      if not self.stopped.exchange(True):
        self.exception = exception
        self.doneAction()

    def onCompleted(self):
      if not self.stopped.exchange(True):
        self.doneAction()
Example #3
0
        def __init__(self, onNext, done):
            self.onNextAction = onNext
            self.doneAction = done

            self.index = 0
            self.stopped = Atomic(False)
            self.exception = None
Example #4
0
  def __init__(self, scheduler, observer):
    super(ScheduledObserver, self).__init__()
    self.scheduler = scheduler
    self.observer = observer
    self.state = Atomic(ScheduledObserver.STOPPED, self.lock)
    self.disposable = SerialDisposable()

    self.failed = False
    self.exception = None
    self.completed = False

    self.queue = Queue()
    self.dispatcherJob = None
    self.dispatcherEvent = Semaphore(0)
Example #5
0
class Sink(Disposable):
  """Base class for implementation of query operators, providing
  a lightweight sink that can be disposed to mute the outgoing observer."""

  def __init__(self, observer, cancel):
    super(Sink, self).__init__()
    self.observer = observer
    self.cancel = Atomic(cancel)

  def dispose(self):
    self.observer = NoopObserver.instance

    cancel = self.cancel.exchange(None)

    if cancel != None:
      cancel.dispose()

  class Forewarder(Observer):
    def __init__(self, foreward):
      self.foreward = foreward

    def onNext(self, value):
      self.foreward.observer.onNext(value)

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

    def onCompleted(self):
      self.foreward.observer.onCompleted()
      self.foreward.dispose()

  def getForewarder(self):
    return self.Forewarder(self)
Example #6
0
    def __init__(self, onNext, done):
      self.onNextAction = onNext
      self.doneAction = done

      self.index = 0
      self.stopped = Atomic(False)
      self.exception = None
Example #7
0
class Sink(Disposable):
    """Base class for implementation of query operators, providing
  a lightweight sink that can be disposed to mute the outgoing observer."""
    def __init__(self, observer, cancel):
        super(Sink, self).__init__()
        self.observer = observer
        self.cancel = Atomic(cancel)

    def dispose(self):
        self.observer = NoopObserver.instance

        cancel = self.cancel.exchange(None)

        if cancel != None:
            cancel.dispose()

    class Forewarder(Observer):
        def __init__(self, foreward):
            self.foreward = foreward

        def onNext(self, value):
            self.foreward.observer.onNext(value)

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

        def onCompleted(self):
            self.foreward.observer.onCompleted()
            self.foreward.dispose()

    def getForewarder(self):
        return self.Forewarder(self)
Example #8
0
  class InnerDisposable(Disposable):
    def __init__(self, parent):
      self.parent = Atomic(parent)

    def dispose(self):
      parent = self.parent.exchange(None)

      if parent != None:
        parent.release()
Example #9
0
    class InnerDisposable(Disposable):
        def __init__(self, parent):
            self.parent = Atomic(parent)

        def dispose(self):
            parent = self.parent.exchange(None)

            if parent != None:
                parent.release()
Example #10
0
class ObserverBase(Cancelable, Observer):
  """Abstract base class for implementations
  of the IObserver interface.
  This base class enforces the grammar of observers
  where OnError and OnCompleted are terminal messages."""

  def __init__(self):
    super(ObserverBase, self).__init__()
    self.isStopped = Atomic(False, self.lock)

  def onNext(self, value):
    with self.lock:
      if self.isStopped.value:
        return

      self.onNextCore(value)

  def onError(self, exception):
    if not self.isStopped.exchange(True):
      self.onErrorCore(exception)

  def onCompleted(self):
    if not self.isStopped.exchange(True):
      self.onCompletedCore()

  def dispose(self):
    self.isStopped.value = True

  def fail(self, exception):
    if self.isStopped.exchange(True):
      # isStopped was already true
      return False
    else:
      self.onErrorCore(exception)
      return True

  def onNextCore(self, value):
    raise NotImplementedError()

  def onErrorCore(self, exception):
    raise NotImplementedError()

  def onCompletedCore(self):
    raise NotImplementedError()
Example #11
0
class ObserverBase(Cancelable, Observer):
  """Abstract base class for implementations
  of the IObserver interface.
  This base class enforces the grammar of observers
  where OnError and OnCompleted are terminal messages."""

  def __init__(self):
    super(ObserverBase, self).__init__()
    self.isStopped = Atomic(False, self.lock)

  def onNext(self, value):
    with self.lock:
      if self.isStopped.value:
        return

      self.onNextCore(value)

  def onError(self, exception):
    if not self.isStopped.exchange(True):
      self.onErrorCore(exception)

  def onCompleted(self):
    if not self.isStopped.exchange(True):
      self.onCompletedCore()

  def dispose(self):
    self.isStopped.value = True

  def fail(self, exception):
    if self.isStopped.exchange(True):
      # isStopped was already true
      return False
    else:
      self.onErrorCore(exception)
      return True

  def onNextCore(self, value):
    raise NotImplementedError()

  def onErrorCore(self, exception):
    raise NotImplementedError()

  def onCompletedCore(self):
    raise NotImplementedError()
Example #12
0
    class Subscription(Disposable):
        def __init__(self, subject, observer):
            self.subject = subject
            self.observer = Atomic(observer)

        def dispose(self):
            old = self.observer.exchange(None)

            if old != None:
                self.subject.unsubscribe(old)
                self.subject = None
Example #13
0
  class Subscription(Disposable):
    def __init__(self, subject, observer):
      self.subject = subject
      self.observer = Atomic(observer)

    def dispose(self):
      old = self.observer.exchange(None)

      if old != None:
        self.subject.unsubscribe(old)
        self.subject = None
Example #14
0
  def __init__(self, scheduler, observer):
    super(ScheduledObserver, self).__init__()
    self.scheduler = scheduler
    self.observer = observer
    self.state = Atomic(ScheduledObserver.STOPPED, self.lock)
    self.disposable = SerialDisposable()

    self.failed = False
    self.exception = None
    self.completed = False

    self.queue = Queue()
    self.dispatcherJob = None
    self.dispatcherEvent = Semaphore(0)
Example #15
0
class CheckedObserver(Observer):
  IDLE = 0
  BUSY = 1
  DONE = 2

  def __init__(self, observer):
    super(CheckedObserver, self).__init__()
    self.observer = observer
    self.state = Atomic(CheckedObserver.IDLE)

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

    try:
      self.observer.onNext(value)
    finally:
      self.state.value = CheckedObserver.IDLE

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

    try:
      self.observer.onError(exception)
    finally:
      self.state.value = CheckedObserver.DONE

  def onCompleted(self):
    self.checkAccess()

    try:
      self.observer.onCompleted()
    finally:
      self.state.value = CheckedObserver.DONE

  def checkAccess(self):
    old = self.state.compareExchange(CheckedObserver.BUSY, CheckedObserver.IDLE)

    if old == CheckedObserver.BUSY:
      raise Exception("This observer is currently busy")
    elif old == CheckedObserver.DONE:
      raise Exception("This observer already terminated")
Example #16
0
class CheckedObserver(Observer):
  IDLE = 0
  BUSY = 1
  DONE = 2

  def __init__(self, observer):
    super(CheckedObserver, self).__init__()
    self.observer = observer
    self.state = Atomic(CheckedObserver.IDLE)

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

    try:
      self.observer.onNext(value)
    finally:
      self.state.value = CheckedObserver.IDLE

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

    try:
      self.observer.onError(exception)
    finally:
      self.state.value = CheckedObserver.DONE

  def onCompleted(self):
    self.checkAccess()

    try:
      self.observer.onCompleted()
    finally:
      self.state.value = CheckedObserver.DONE

  def checkAccess(self):
    old = self.state.compareExchange(CheckedObserver.BUSY, CheckedObserver.IDLE)

    if old == CheckedObserver.BUSY:
      raise Exception("This observer is currently busy")
    elif old == CheckedObserver.DONE:
      raise Exception("This observer already terminated")
Example #17
0
class ObserveOnObserver(ScheduledObserver):
  def __init__(self, scheduler, observer, cancel):
    super(ObserveOnObserver, self).__init__(scheduler, observer)
    self.cancel = Atomic(cancel, self.lock)

  def onNextCore(self, value):
    super(ObserveOnObserver, self).onNextCore(value)
    self.ensureActive()

  def onErrorCore(self, exception):
    super(ObserveOnObserver, self).onErrorCore(exception)
    self.ensureActive()

  def onCompletedCore(self):
    super(ObserveOnObserver, self).onCompletedCore()
    self.ensureActive()

  def dispose(self):
    super(ObserveOnObserver, self).dispose()

    old = self.cancel.exchange(None)

    if old != None:
      old.dispose()
Example #18
0
class ObserveOnObserver(ScheduledObserver):
  def __init__(self, scheduler, observer, cancel):
    super(ObserveOnObserver, self).__init__(scheduler, observer)
    self.cancel = Atomic(cancel, self.lock)

  def onNextCore(self, value):
    super(ObserveOnObserver, self).onNextCore(value)
    self.ensureActive()

  def onErrorCore(self, exception):
    super(ObserveOnObserver, self).onErrorCore(exception)
    self.ensureActive()

  def onCompletedCore(self):
    super(ObserveOnObserver, self).onCompletedCore()
    self.ensureActive()

  def dispose(self):
    super(ObserveOnObserver, self).dispose()

    old = self.cancel.exchange(None)

    if old != None:
      old.dispose()
Example #19
0
 def __init__(self, observer):
   super(CheckedObserver, self).__init__()
   self.observer = observer
   self.state = Atomic(CheckedObserver.IDLE)
Example #20
0
class Subject(Observable, Observer):
  def __init__(self):
    super(Subject, self).__init__()
    self.isDisposed = False
    self.isStopped = False
    self.exception = None
    self.observer = Atomic(NoopObserver.instance)

  def onCompleted(self):
    old = None
    new = DoneObserver.completed

    while True:
      old = self.observer.value

      if old is DoneObserver.completed or isinstance(old, DoneObserver):
        break

      current = self.observer.compareExchange(new, old)

      if old is current:
        break

    old.onCompleted()

  def onError(self, exception):
    old = None
    new = DoneObserver(exception)

    while True:
      old = self.observer.value

      if old is DoneObserver.completed or isinstance(old, DoneObserver):
        break

      current = self.observer.compareExchange(new, old)

      if old is current:
        break

    old.onError(exception)

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

  class Subscription(Disposable):
    def __init__(self, subject, observer):
      self.subject = subject
      self.observer = Atomic(observer)

    def dispose(self):
      old = self.observer.exchange(None)

      if old != None:
        self.subject.unsubscribe(old)
        self.subject = None

  def subscribeCore(self, observer):
    old = None
    new = None

    while True:
      old = self.observer.value

      if old is DisposedObserver.instance:
        raise Exception("Object has been disposed")

      if old is DoneObserver.completed:
        observer.onCompleted()
        return Disposable.empty()

      if isinstance(old, DoneObserver):
        observer.onError(old.exception)
        return Disposable.empty()

      if old is NoopObserver.instance:
        new = observer
      else:
        if isinstance(old, ListObserver):
          new = old.add(observer)
        else:
          new = ListObserver((old, observer))

      current = self.observer.compareExchange(new, old)

      if old is current:
        break

    return self.Subscription(self, observer)

  def unsubscribe(self, observer):
    old = None
    new = None

    while True:
      old = self.observer.value

      if old is DisposedObserver.instance or isinstance(old, DoneObserver):
        return

      if isinstance(old, ListObserver):
        new = old.remove(observer)
      elif observer is not old:
        return
      else:
        new = NoopObserver.instance

      current = self.observer.compareExchange(new, old)

      if old is current:
        return

  def dispose(self):
    self.observer.exchange(NoopObserver.instance)

  @staticmethod
  def create(observer, observable):
    return AnonymousSubject(observer, observable)

  @staticmethod
  def synchronize(subject, scheduler=None):
    if scheduler == None:
      return AnonymousSubject(Observer.synchronize(subject), subject)
    else:
      return AnonymousSubject(Observer.synchronize(subject), subject.observeOn(scheduler))
Example #21
0
 def __init__(self, parent, observer, cancel):
   super(SkipUntilTime.Sink, self).__init__(observer, cancel)
   self.parent = parent
   self.open = Atomic(False)
Example #22
0
 def __init__(self):
   super(Subject, self).__init__()
   self.isDisposed = False
   self.isStopped = False
   self.exception = None
   self.observer = Atomic(NoopObserver.instance)
Example #23
0
 def __init__(self, observer):
   super(CheckedObserver, self).__init__()
   self.observer = observer
   self.state = Atomic(CheckedObserver.IDLE)
Example #24
0
 def __init__(self, parent):
     self.parent = Atomic(parent)
Example #25
0
 def __init__(self):
     super(Subject, self).__init__()
     self.isDisposed = False
     self.isStopped = False
     self.exception = None
     self.observer = Atomic(NoopObserver.instance)
Example #26
0
 def __init__(self):
   super(ObserverBase, self).__init__()
   self.isStopped = Atomic(False, self.lock)
Example #27
0
class Subject(Observable, Observer):
    def __init__(self):
        super(Subject, self).__init__()
        self.isDisposed = False
        self.isStopped = False
        self.exception = None
        self.observer = Atomic(NoopObserver.instance)

    def onCompleted(self):
        old = None
        new = DoneObserver.completed

        while True:
            old = self.observer.value

            if old is DoneObserver.completed or isinstance(old, DoneObserver):
                break

            current = self.observer.compareExchange(new, old)

            if old is current:
                break

        old.onCompleted()

    def onError(self, exception):
        old = None
        new = DoneObserver(exception)

        while True:
            old = self.observer.value

            if old is DoneObserver.completed or isinstance(old, DoneObserver):
                break

            current = self.observer.compareExchange(new, old)

            if old is current:
                break

        old.onError(exception)

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

    class Subscription(Disposable):
        def __init__(self, subject, observer):
            self.subject = subject
            self.observer = Atomic(observer)

        def dispose(self):
            old = self.observer.exchange(None)

            if old != None:
                self.subject.unsubscribe(old)
                self.subject = None

    def subscribeCore(self, observer):
        old = None
        new = None

        while True:
            old = self.observer.value

            if old is DisposedObserver.instance:
                raise Exception("Object has been disposed")

            if old is DoneObserver.completed:
                observer.onCompleted()
                return Disposable.empty()

            if isinstance(old, DoneObserver):
                observer.onError(old.exception)
                return Disposable.empty()

            if old is NoopObserver.instance:
                new = observer
            else:
                if isinstance(old, ListObserver):
                    new = old.add(observer)
                else:
                    new = ListObserver((old, observer))

            current = self.observer.compareExchange(new, old)

            if old is current:
                break

        return self.Subscription(self, observer)

    def unsubscribe(self, observer):
        old = None
        new = None

        while True:
            old = self.observer.value

            if old is DisposedObserver.instance or isinstance(
                    old, DoneObserver):
                return

            if isinstance(old, ListObserver):
                new = old.remove(observer)
            elif observer is not old:
                return
            else:
                new = NoopObserver.instance

            current = self.observer.compareExchange(new, old)

            if old is current:
                return

    def dispose(self):
        self.observer.exchange(NoopObserver.instance)

    @staticmethod
    def create(observer, observable):
        return AnonymousSubject(observer, observable)

    @staticmethod
    def synchronize(subject, scheduler=None):
        if scheduler == None:
            return AnonymousSubject(Observer.synchronize(subject), subject)
        else:
            return AnonymousSubject(Observer.synchronize(subject),
                                    subject.observeOn(scheduler))
Example #28
0
 def __init__(self, parent, observer, cancel):
     super(Timer.PeriodSink, self).__init__(observer, cancel)
     self.parent = parent
     self.pendingTickCount = Atomic(0)
Example #29
0
 def __init__(self, observer, cancel):
     super(Sink, self).__init__()
     self.observer = observer
     self.cancel = Atomic(cancel)
Example #30
0
 def __init__(self, observer, cancel):
   super(Sink, self).__init__()
   self.observer = observer
   self.cancel = Atomic(cancel)
Example #31
0
class ScheduledObserver(ObserverBase):
  STOPPED = 0
  RUNNING = 1
  PENDING = 2
  FAULTED = 9

  def __init__(self, scheduler, observer):
    super(ScheduledObserver, self).__init__()
    self.scheduler = scheduler
    self.observer = observer
    self.state = Atomic(ScheduledObserver.STOPPED, self.lock)
    self.disposable = SerialDisposable()

    self.failed = False
    self.exception = None
    self.completed = False

    self.queue = Queue()
    self.dispatcherJob = None
    self.dispatcherEvent = Semaphore(0)

  def ensureDispatcher(self):
    if self.dispatcherJob != None:
      return

    with self.lock:
      if self.dispatcherJob == None:
        self.dispatcherJob = self.scheduler.scheduleLongRunning(self.dispatch)
        self.disposable.disposable = CompositeDisposable(
          self.dispatcherJob,
          Disposable.create(self.dispatcherEvent.release)
        )

  def dispatch(self, cancel):
    while True:
      self.dispatcherEvent.acquire()

      if cancel.isDisposed:
        return

      while True:
        next = self.queue.get()

        try:
          self.observer.onNext(next)
        except Exception as e:
          self.clearQueue()
          raise e

        self.dispatcherEvent.acquire()

        if cancel.isDisposed:
          return

      if self.failed:
        self.observer.onError(self.exception)
        self.dispose()

        return

      if self.completed:
        self.observer.onCompleted()
        self.dispose()

        return

  def ensureActive(self, n = 1):
    if self.scheduler.isLongRunning:
      while n > 0:
        self.dispatcherEvent.release()
        n -= 1

        self.ensureDispatcher()
    else:
      self.ensureActiveSlow()

  def ensureActiveSlow(self):
    isOwner = False

    while True:
      old = self.state.compareExchange(
        ScheduledObserver.RUNNING,
        ScheduledObserver.STOPPED
      )

      if old == ScheduledObserver.STOPPED:
        isOwner = True
        break
      elif old == ScheduledObserver.FAULTED:
        return
      elif (
          (old == ScheduledObserver.PENDING or old == ScheduledObserver.RUNNING) and
          self.state.compareExchange(ScheduledObserver.PENDING, ScheduledObserver.RUNNING) == ScheduledObserver.RUNNING
        ):
        break

    if isOwner:
      self.disposable = self.scheduler.scheduleRecursiveWithState(None, self.run)

  def run(self, state, continuation):
    next = None

    while True:
      try:
        next = self.queue.get_nowait()
      except Empty:
        next = None

      if next != None:
        break

      if self.failed:
        # wait until the queue is drained
        if not self.queue.empty():
          continue

        self.state.value = ScheduledObserver.STOPPED

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

        return

      if self.completed:
        # wait until the queue is drained
        if not self.queue.empty():
          continue

        self.state.value = ScheduledObserver.STOPPED

        self.observer.onCompleted()
        self.dispose()

        return

      old = self.state.compareExchange(
        ScheduledObserver.STOPPED,
        ScheduledObserver.RUNNING
      )

      if old == ScheduledObserver.RUNNING or old == ScheduledObserver.FAULTED:
        return

      # assert(old == ScheduledObserver.PENDING)

      self.state.value = ScheduledObserver.RUNNING
    #end while

    # we found an item, so next != None
    self.state.value = ScheduledObserver.RUNNING

    try:
      self.observer.onNext(next)
    except Exception as e:
      self.state.value = ScheduledObserver.FAULTED
      self.clearQueue()

      raise e

    continuation(state)

  def onNextCore(self, value):
    self.queue.put(value)

  def onErrorCore(self, exception):
    self.exception = exception
    self.failed = True

  def onCompletedCore(self):
    self.completed = True

  def clearQueue(self):
    try:
      while True:
        self.queue.get()
    except Empty:
      pass

  def dispose(self):
    super(ScheduledObserver, self).dispose()
    self.disposable.dispose()
Example #32
0
    class PeriodSink(rx.linq.sink.Sink):
        def __init__(self, parent, observer, cancel):
            super(Timer.PeriodSink, self).__init__(observer, cancel)
            self.parent = parent
            self.pendingTickCount = Atomic(0)

        def run(self):
            if self.parent.isAbsolute:
                return self.parent.scheduler.scheduleWithAbsoluteAndState(
                    None, self.parent.dueTime, self.invokeStart)
            else:
                dueTime = self.parent.dueTime

                if dueTime == self.parent.period:
                    return self.parent.scheduler.schedulePeriodicWithState(
                        0, self.parent.period, self.tick)

                return self.parent.scheduler.scheduleWithRelativeAndState(
                    None, dueTime, self.invokeStart)

        def tick(self, count):
            self.observer.onNext(count)
            return count + 1

        def invokeStart(self, scheduler, state):
            #
            # Notice the first call to OnNext will introduce skew if it takes significantly long when
            # using the following naive implementation:
            #
            #    Code:  base._observer.OnNext(0L);
            #           return self.SchedulePeriodicEmulated(1L, _period, (Func<long, long>)Tick);
            #
            # What we're saying here is that Observable.Timer(dueTime, period) is pretty much the same
            # as writing Observable.Timer(dueTime).Concat(Observable.Interval(period)).
            #
            #    Expected:  dueTime
            #                  |
            #                  0--period--1--period--2--period--3--period--4--...
            #                  |
            #                  +-OnNext(0L)-|
            #
            #    Actual:    dueTime
            #                  |
            #                  0------------#--period--1--period--2--period--3--period--4--...
            #                  |
            #                  +-OnNext(0L)-|
            #
            # Different solutions for this behavior have different problems:
            #
            # 1. Scheduling the periodic job first and using an AsyncLock to serialize the OnNext calls
            #    has the drawback that InvokeStart may never return. This happens when every callback
            #    doesn't meet the period's deadline, hence the periodic job keeps queueing stuff up. In
            #    this case, InvokeStart stays the owner of the AsyncLock and the call to Wait will never
            #    return, thus not allowing any interleaving of work on this scheduler's logical thread.
            #
            # 2. Scheduling the periodic job first and using a (blocking) synchronization primitive to
            #    signal completion of the OnNext(0L) call to the Tick call requires quite a bit of state
            #    and careful handling of the case when OnNext(0L) throws. What's worse is the blocking
            #    behavior inside Tick.
            #
            # In order to avoid blocking behavior, we need a scheme much like SchedulePeriodic emulation
            # where work to dispatch OnNext(n + 1) is delegated to a catch up loop in case OnNext(n) was
            # still running. Because SchedulePeriodic emulation exhibits such behavior in all cases, we
            # only need to deal with the overlap of OnNext(0L) with future periodic OnNext(n) dispatch
            # jobs. In the worst case where every callback takes longer than the deadline implied by the
            # period, the periodic job will just queue up work that's dispatched by the tail-recursive
            # catch up loop. In the best case, all work will be dispatched on the periodic scheduler.
            #

            #
            # We start with one tick pending because we're about to start doing OnNext(0L).
            #

            self.pendingTickCount.value = 1

            d = SingleAssignmentDisposable()
            self.periodic = d
            d.disposable = scheduler.schedulePeriodicWithState(
                1, self.parent.period, self.tock)

            try:
                self.observer.onNext(0)
            except Exception as e:
                d.dispose()
                raise e

            #
            # If the periodic scheduling job already ran before we finished dispatching the OnNext(0L)
            # call, we'll find pendingTickCount to be > 1. In this case, we need to catch up by dispatching
            # subsequent calls to OnNext as fast as possible, but without running a loop in order to ensure
            # fair play with the scheduler. So, we run a tail-recursive loop in CatchUp instead.
            #

            if self.pendingTickCount.dec() > 0:
                c = SingleAssignmentDisposable()
                c.disposable = scheduler.scheduleRecursiveWithState(
                    1, self.catchUp)

                return CompositeDisposable(d, c)

            return d

        def tock(self, count):
            if self.pendingTickCount.inc() == 1:
                self.observer.onNext(count)
                self.pendingTickCount.dec()

            return count + 1

        def catchUp(self, count, recurse):
            try:
                self.observer.onNext(count)
            except Exception as e:
                self.periodic.dispose()
                raise e

            #
            # We can simply bail out if we decreased the tick count to 0. In that case, the Tock
            # method will take over when it sees the 0 -> 1 transition.
            #
            if self.pendingTickCount.dec() > 0:
                recurse(count + 1)
Example #33
0
 def __init__(self):
     super(Cancelable, self).__init__()
     self._isDisposed = Atomic(False)
Example #34
0
 def __init__(self, subject, observer):
     self.subject = subject
     self.observer = Atomic(observer)
Example #35
0
 def __init__(self, scheduler, observer, cancel):
   super(ObserveOnObserver, self).__init__(scheduler, observer)
   self.cancel = Atomic(cancel, self.lock)
Example #36
0
 def __init__(self, subject, observer):
   self.subject = subject
   self.observer = Atomic(observer)
Example #37
0
 def __init__(self):
   super(ObserverBase, self).__init__()
   self.isStopped = Atomic(False, self.lock)
Example #38
0
class ScheduledObserver(ObserverBase):
  STOPPED = 0
  RUNNING = 1
  PENDING = 2
  FAULTED = 9

  def __init__(self, scheduler, observer):
    super(ScheduledObserver, self).__init__()
    self.scheduler = scheduler
    self.observer = observer
    self.state = Atomic(ScheduledObserver.STOPPED, self.lock)
    self.disposable = SerialDisposable()

    self.failed = False
    self.exception = None
    self.completed = False

    self.queue = Queue()
    self.dispatcherJob = None
    self.dispatcherEvent = Semaphore(0)

  def ensureDispatcher(self):
    if self.dispatcherJob != None:
      return

    with self.lock:
      if self.dispatcherJob == None:
        self.dispatcherJob = self.scheduler.scheduleLongRunning(self.dispatch)
        self.disposable.disposable = CompositeDisposable(
          self.dispatcherJob,
          Disposable.create(self.dispatcherEvent.release)
        )

  def dispatch(self, cancel):
    while True:
      self.dispatcherEvent.acquire()

      if cancel.isDisposed:
        return

      while True:
        next = self.queue.get()

        try:
          self.observer.onNext(next)
        except Exception as e:
          self.clearQueue()
          raise e

        self.dispatcherEvent.acquire()

        if cancel.isDisposed:
          return

      if self.failed:
        self.observer.onError(self.exception)
        self.dispose()

        return

      if self.completed:
        self.observer.onCompleted()
        self.dispose()

        return

  def ensureActive(self, n = 1):
    if self.scheduler.isLongRunning:
      while n > 0:
        self.dispatcherEvent.release()
        n -= 1

        self.ensureDispatcher()
    else:
      self.ensureActiveSlow()

  def ensureActiveSlow(self):
    isOwner = False

    while True:
      old = self.state.compareExchange(
        ScheduledObserver.RUNNING,
        ScheduledObserver.STOPPED
      )

      if old == ScheduledObserver.STOPPED:
        isOwner = True
        break
      elif old == ScheduledObserver.FAULTED:
        return
      elif (
          (old == ScheduledObserver.PENDING or old == ScheduledObserver.RUNNING) and
          self.state.compareExchange(ScheduledObserver.PENDING, ScheduledObserver.RUNNING) == ScheduledObserver.RUNNING
        ):
        break

    if isOwner:
      self.disposable = self.scheduler.scheduleRecursiveWithState(None, self.run)

  def run(self, state, continuation):
    next = None

    while True:
      try:
        next = self.queue.get_nowait()
      except Empty:
        next = None

      if next != None:
        break

      if self.failed:
        # wait until the queue is drained
        if not self.queue.empty():
          continue

        self.state.value = ScheduledObserver.STOPPED

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

        return

      if self.completed:
        # wait until the queue is drained
        if not self.queue.empty():
          continue

        self.state.value = ScheduledObserver.STOPPED

        self.observer.onCompleted()
        self.dispose()

        return

      old = self.state.compareExchange(
        ScheduledObserver.STOPPED,
        ScheduledObserver.RUNNING
      )

      if old == ScheduledObserver.RUNNING or old == ScheduledObserver.FAULTED:
        return

      # assert(old == ScheduledObserver.PENDING)

      self.state.value = ScheduledObserver.RUNNING
    #end while

    # we found an item, so next != None
    self.state.value = ScheduledObserver.RUNNING

    try:
      self.observer.onNext(next)
    except Exception as e:
      self.state.value = ScheduledObserver.FAULTED
      self.clearQueue()

      raise e

    continuation(state)

  def onNextCore(self, value):
    self.queue.put(value)

  def onErrorCore(self, exception):
    self.exception = exception
    self.failed = True

  def onCompletedCore(self):
    self.completed = True

  def clearQueue(self):
    try:
      while True:
        self.queue.get()
    except Empty:
      pass

  def dispose(self):
    super(ScheduledObserver, self).dispose()
    self.disposable.dispose()
Example #39
0
 def __init__(self, parent):
   self.parent = Atomic(parent)
Example #40
0
 def __init__(self, scheduler, observer, cancel):
   super(ObserveOnObserver, self).__init__(scheduler, observer)
   self.cancel = Atomic(cancel, self.lock)