def test_mutabledisposable_dispose():
    disp = [False]
    m = SerialDisposable()

    def action():
        disp[0] = True
    d = Disposable(action)
    m.disposable = d

    assert d == m.disposable
    assert not disp[0]
    m.dispose()
    assert disp[0]
    assert m.disposable == None
示例#2
0
def test_mutabledisposable_dispose():
    disp = [False]
    m = SerialDisposable()

    def action():
        disp[0] = True

    d = Disposable(action)
    m.disposable = d

    assert d == m.disposable
    assert not disp[0]
    m.dispose()
    assert disp[0]
    assert m.disposable == None
def test_mutabledisposable_replaceafterdispose():
    disp1 = [False]
    disp2 = [False]
    m = SerialDisposable()
    m.dispose()

    def action1():
        disp1[0] = True
    d1 = Disposable(action1)
    m.disposable = d1

    assert m.disposable == None
    assert disp1[0]

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

    assert m.disposable == None
    assert disp2[0]
示例#4
0
def test_mutabledisposable_replaceafterdispose():
    disp1 = [False]
    disp2 = [False]
    m = SerialDisposable()
    m.dispose()

    def action1():
        disp1[0] = True

    d1 = Disposable(action1)
    m.disposable = d1

    assert m.disposable == None
    assert disp1[0]

    def action2():
        disp2[0] = True

    d2 = Disposable(action2)
    m.disposable = d2

    assert m.disposable == None
    assert disp2[0]
示例#5
0
class PeriodicTimer(object):
    """A timer that runs every interval seconds, can shift in time"""
    def __init__(self, interval, action):
        super(PeriodicTimer, self).__init__()
        self.interval = interval
        self.action = action
        self.timerDisposable = SerialDisposable()

    def start(self):
        timer = Timer(self.interval, self._execute)

        self.timerDisposable.disposable = Disposable.create(timer.cancel)

        timer.start()

        return self.timerDisposable

    def cancel(self):
        self.timerDisposable.dispose()

    def _execute(self):
        self.action()
        self.run()
示例#6
0
class PeriodicTimer(object):
  """A timer that runs every interval seconds, can shift in time"""
  def __init__(self, interval, action):
    super(PeriodicTimer, self).__init__()
    self.interval = interval
    self.action = action
    self.timerDisposable = SerialDisposable()

  def start(self):
    timer = Timer(self.interval, self._execute)

    self.timerDisposable.disposable = Disposable.create(timer.cancel)

    timer.start()

    return self.timerDisposable

  def cancel(self):
    self.timerDisposable.dispose()

  def _execute(self):
    self.action()
    self.run()
示例#7
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()
示例#8
0
class ScheduledObserver(ObserverBase):
    def __init__(self, scheduler: abc.Scheduler,
                 observer: abc.Observer) -> None:
        super().__init__()

        self.scheduler = scheduler
        self.observer = observer

        self.lock = threading.RLock()
        self.is_acquired = False
        self.has_faulted = False
        self.queue: List[Action] = []
        self.disposable = SerialDisposable()

        # Note to self: list append is thread safe
        # http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm

    def _on_next_core(self, value: Any) -> None:
        def action():
            self.observer.on_next(value)

        self.queue.append(action)

    def _on_error_core(self, error: Exception) -> None:
        def action():
            self.observer.on_error(error)

        self.queue.append(action)

    def _on_completed_core(self) -> None:
        def action():
            self.observer.on_completed()

        self.queue.append(action)

    def ensure_active(self) -> None:
        is_owner = False

        with self.lock:
            if not self.has_faulted and self.queue:
                is_owner = not self.is_acquired
                self.is_acquired = True

        if is_owner:
            self.disposable.disposable = self.scheduler.schedule(self.run)

    def run(self, scheduler: abc.Scheduler, state: Any) -> None:
        parent = self

        with self.lock:
            if parent.queue:
                work = parent.queue.pop(0)
            else:
                parent.is_acquired = False
                return

        try:
            work()
        except Exception:
            with self.lock:
                parent.queue = []
                parent.has_faulted = True
            raise

        self.scheduler.schedule(self.run)

    def dispose(self) -> None:
        super().dispose()
        self.disposable.dispose()
示例#9
0
文件: delay.py 项目: aguil/RxPython
    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()
示例#10
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(ThrottleObservable.Sink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.value = None
      self.hasValue = False
      self.throttleDisposable = SerialDisposable()
      self.resourceId = 0

      subscription = self.parent.source.subscribeSafe(self)

      return CompositeDisposable(subscription, self.throttleDisposable)

    def onNext(self, value):
      throttle = None

      try:
        throttle = self.parent.throttleSelector(value)
      except Exception as e:
        with self.gate:
          self.observer.onError(e)
          self.dispose()

        return

      currentId = 0

      with self.gate:
        self.hasValue = True
        self.value = value
        self.resourceId += 1
        currentId = self.resourceId

      d = SingleAssignmentDisposable()
      self.throttleDisposable.disposable = d
      d.disposable = throttle.subscribeSafe(self.Delta(self, value, currentId, d))

    def onError(self, exception):
      self.throttleDisposable.dispose()

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

        self.hasValue = False
        self.resourceId += 1

    def onCompleted(self):
      self.throttleDisposable.dispose()

      with self.gate:
        if self.hasValue:
          self.observer.onNext(self.value)

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

        self.hasValue = False
        self.resourceId += 1

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

      def onNext(self, value):
        with self.parent.gate:
          if self.parent.hasValue and self.parent.resourceId == self.currentId:
            self.parent.observer.onNext(self.value)

          self.parent.hasValue = False
          self.cancelSelf.dispose()

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

      def onCompleted(self):
        with self.parent.gate:
          if self.parent.hasValue and self.parent.resourceId == self.currentId:
            self.parent.observer.onNext(self.value)

          self.parent.hasValue = False
          self.cancelSelf.dispose()
示例#11
0
  class Sink(rx.linq.sink.Sink):
    def __init__(self, parent, observer, cancel):
      super(ThrottleTime.Sink, self).__init__(observer, cancel)
      self.parent = parent

    def run(self):
      self.gate = RLock()
      self.value = None
      self.hasValue = False
      self.propagatorDisposable = SerialDisposable()
      self.resourceId = 0

      subscription = self.parent.source.subscribeSafe(self)

      return CompositeDisposable(subscription, self.propagatorDisposable)

    def onNext(self, value):
      currentId = 0

      with self.gate:
        self.hasValue = True
        self.value = value
        self.resourceId += 1
        currentId = self.resourceId

      d = SingleAssignmentDisposable()
      self.propagatorDisposable.disposable = d
      d.disposable = self.parent.scheduler.scheduleWithRelativeAndState(
        currentId,
        self.parent.dueTime,
        self.propagate
      )

    def propagate(self, scheduler, currentId):
      with self.gate:
        if self.hasValue and self.resourceId == currentId:
          self.observer.onNext(self.value)
        self.hasValue = False

      return Disposable.empty()

    def onError(self, exception):
      self.propagatorDisposable.dispose()

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

        self.hasValue = False
        self.resourceId += 1

    def onCompleted(self):
      self.propagatorDisposable.dispose()

      with self.gate:
        if self.hasValue:
          self.observer.onNext(self.value)

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

        self.hasValue = False
        self.resourceId += 1
示例#12
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()
示例#13
0
文件: delay.py 项目: aguil/RxPython
  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()
示例#14
0
class ScheduledSingle(Single):
    def __init__(self, scheduler: typing.Scheduler, single: Single) -> None:
        super().__init__()

        self.scheduler = scheduler
        self.single = single

        self.lock = threading.RLock()
        self.is_acquired = False
        self.has_faulted = False
        self.queue: List[typing.Action] = []
        self.disposable = SerialDisposable()

    def on_next(self, value):
        def action():
            self.single.on_next(value)

        self.queue.append(action)
        self.ensure_active()

    def on_error(self, error: Exception):
        def action():
            self.single.on_error(error)

        self.queue.append(action)
        self.ensure_active()

    def ensure_active(self) -> None:
        is_owner = False

        with self.lock:
            if not self.has_faulted and self.queue:
                is_owner = not self.is_acquired
                self.is_acquired = True

        if is_owner:
            self.disposable.disposable = self.scheduler.schedule(self.run)

    def run(self, _, __) -> None:
        parent = self

        with self.lock:
            if parent.queue:
                work = parent.queue.pop(0)
            else:
                parent.is_acquired = False
                return

        try:
            work()
        except Exception:
            with self.lock:
                parent.queue = []
                parent.has_faulted = True
            raise

        self.scheduler.schedule(self.run)

    def dispose(self) -> None:
        self.is_stopped = True
        self.disposable.dispose()
class ScheduledObserver(ObserverBase):
    def __init__(self, scheduler: abc.Scheduler, observer: abc.Observer) -> None:
        super().__init__()

        self.scheduler = scheduler
        self.observer = observer

        self.lock = threading.RLock()
        self.is_acquired = False
        self.has_faulted = False
        self.queue: List[Action] = []
        self.disposable = SerialDisposable()

        # Note to self: list append is thread safe
        # http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm

    def _on_next_core(self, value: Any) -> None:
        def action():
            self.observer.on_next(value)
        self.queue.append(action)

    def _on_error_core(self, error: Exception) -> None:
        def action():
            self.observer.on_error(error)
        self.queue.append(action)

    def _on_completed_core(self) -> None:
        def action():
            self.observer.on_completed()
        self.queue.append(action)

    def ensure_active(self) -> None:
        is_owner = False

        with self.lock:
            if not self.has_faulted and self.queue:
                is_owner = not self.is_acquired
                self.is_acquired = True

        if is_owner:
            self.disposable.disposable = self.scheduler.schedule(self.run)

    def run(self, scheduler: abc.Scheduler, state: Any) -> None:
        parent = self

        with self.lock:
            if parent.queue:
                work = parent.queue.pop(0)
            else:
                parent.is_acquired = False
                return

        try:
            work()
        except Exception:
            with self.lock:
                parent.queue = []
                parent.has_faulted = True
            raise

        self.scheduler.schedule(self.run)

    def dispose(self) -> None:
        super().dispose()
        self.disposable.dispose()