Beispiel #1
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")
Beispiel #2
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")
Beispiel #3
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()
Beispiel #4
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))
Beispiel #5
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()
Beispiel #6
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))