class AsyncLockScheduler(Scheduler): def __init__(self): super(ImmediateScheduler.AsyncLockScheduler, self).__init__() self.gate = None def _scheduleCore(self, state, action): m = SingleAssignmentDisposable() def gated(): if not m.isDisposed: m.disposable = action(self, state) if self.gate == None: self.gate = AsyncLock() self.gate.wait(gated) return m def _scheduleRelativeCore(self, state, dueTime, action): m = SingleAssignmentDisposable() now = Scheduler.now() def gated(): if not m.isDisposed: elapsed = Scheduler.now() - now dt = Scheduler.normalize(dueTime - elapsed) if dt > 0: sleep(dt) if not m.isDisposed: m.disposable = action(self, state) if self.gate == None: self.gate = AsyncLock() self.gate.wait(gated) return m def _scheduleAbsoluteCore(self, state, dueTime, action): return self.scheduleWithRelativeAndState(state, dueTime - self.now(), action)
def schedulePeriodicWithState(self, state, interval, action): gate = AsyncLock() def gated(): state = action(state) timer = PeriodicTimer(interval, lambda: gate.wait(gated)) cancel = timer.start() return CompositeDisposable(cancel, gate)
class TailRecursiveSink(Sink): def __init__(self, observer, cancel): super(TailRecursiveSink, self).__init__(observer, cancel) @staticmethod def unpack(source): while hasattr(source, 'eval'): source = source.eval() return source def run(self, sources): self.isDisposed = False self.subscription = SerialDisposable() self.gate = AsyncLock() self.stack = [] self.length = [] self.stack.append(iter(sources)) try: length = len(sources) except TypeError: self.length.append(-1) else: self.length.append(length) def scheduled(continuation): self.recurse = continuation self.gate.wait(self.moveNext) cancel = Scheduler.tailRecursion.scheduleRecursive(scheduled) return CompositeDisposable( self.subscription, cancel, Disposable.create(lambda: self.gate.wait(self.dispose)) ) def extract(self, source): raise NotImplementedError() def moveNext(self): hasCurrent = False current = None while True: if len(self.stack) == 0: break if self.isDisposed: return e = self.stack[-1] l = self.length[-1] try: current = next(e) hasCurrent = True except StopIteration: pass except Exception as e: self.observer.onError(e) self.dispose() return if not hasCurrent: self.stack.pop() self.length.pop() else: r = l - 1 self.length[-1] = r try: current = TailRecursiveSink.unpack(current) except Exception as e: self.observer.onError(e) self.dispose() return # Tail recursive case; drop the current frame. if r == 0: self.stack.pop() self.length.pop() # Flattening of nested sequences. Prevents stack overflow in observers. nextSeq = self.extract(current) if nextSeq != None: self.stack.append(iter(nextSeq)) try: length = len(nextSeq) except TypeError: self.length.append(-1) else: self.length.append(length) hasCurrent = False if hasCurrent: break if not hasCurrent: self.done() return d = SingleAssignmentDisposable() self.subscription.disposable = d d.disposable = current.subscribeSafe(self) def dispose(self): self.stack.clear() self.length.clear() self.isDisposed = True def done(self): self.observer.onCompleted() self.dispose()
class TailRecursiveSink(Sink): def __init__(self, observer, cancel): super(TailRecursiveSink, self).__init__(observer, cancel) @staticmethod def unpack(source): while hasattr(source, 'eval'): source = source.eval() return source def run(self, sources): self.isDisposed = False self.subscription = SerialDisposable() self.gate = AsyncLock() self.stack = [] self.length = [] self.stack.append(iter(sources)) try: length = len(sources) except TypeError: self.length.append(-1) else: self.length.append(length) def scheduled(continuation): self.recurse = continuation self.gate.wait(self.moveNext) cancel = Scheduler.tailRecursion.scheduleRecursive(scheduled) return CompositeDisposable( self.subscription, cancel, Disposable.create(lambda: self.gate.wait(self.dispose))) def extract(self, source): raise NotImplementedError() def moveNext(self): hasCurrent = False current = None while True: if len(self.stack) == 0: break if self.isDisposed: return e = self.stack[-1] l = self.length[-1] try: current = next(e) hasCurrent = True except StopIteration: pass except Exception as e: self.observer.onError(e) self.dispose() return if not hasCurrent: self.stack.pop() self.length.pop() else: r = l - 1 self.length[-1] = r try: current = TailRecursiveSink.unpack(current) except Exception as e: self.observer.onError(e) self.dispose() return # Tail recursive case; drop the current frame. if r == 0: self.stack.pop() self.length.pop() # Flattening of nested sequences. Prevents stack overflow in observers. nextSeq = self.extract(current) if nextSeq != None: self.stack.append(iter(nextSeq)) try: length = len(nextSeq) except TypeError: self.length.append(-1) else: self.length.append(length) hasCurrent = False if hasCurrent: break if not hasCurrent: self.done() return d = SingleAssignmentDisposable() self.subscription.disposable = d d.disposable = current.subscribeSafe(self) def dispose(self): self.stack.clear() self.length.clear() self.isDisposed = True def done(self): self.observer.onCompleted() self.dispose()