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")
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()
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))
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))