def test_mutabledisposable_replaceafterdispose(): disp1 = False disp2 = False m = SerialDisposable() m.dispose() def action1(): nonlocal disp1 disp1 = True d1 = Disposable(action1) m.disposable = d1 assert m.disposable == None assert disp1 def action2(): nonlocal disp2 disp2 = True d2 = Disposable(action2) m.disposable = d2 m.disposable == None assert disp2
class ScheduledObserver(AbstractObserver): def __init__(self, scheduler, observer): super(ScheduledObserver, self).__init__() self.scheduler = scheduler self.observer = observer self.is_acquired = False self.has_faulted = False self.queue = [] self.disposable = SerialDisposable() def next(self, value): def func(): self.observer.on_next(value) self.queue.append(func) def error(self, exception): def func(): self.observer.on_error(exception) self.queue.append(func) def completed(self): def func(): self.observer.on_completed() self.queue.append(func) def ensure_active(self): is_owner, parent = False, self if not self.has_faulted and len(self.queue): is_owner = not self.is_acquired self.is_acquired = True if is_owner: def action(action1, state): work = None if len(parent.queue): work = parent.queue.pop(0) else: parent.is_acquired = False return try: work() except Exception as ex: parent.queue = [] parent.has_faulted = True raise ex action1() self.disposable.disposable = self.scheduler.schedule_recursive(action) def dispose(self): super(ScheduledObserver, self).dispose() self.disposable.dispose()
def test_mutabledisposable_dispose(): disp = [False] m = SerialDisposable() def action(): disp[0] = True d = Disposable.create(action) m.disposable = d assert d == m.disposable assert not disp[0] m.dispose() assert disp[0] assert m.disposable == None
def test_mutabledisposable_dispose(): disp = False m = SerialDisposable() def action(): nonlocal disp disp = True d = Disposable(action) m.disposable = d assert d == m.disposable assert not disp m.dispose() assert disp assert m.disposable == None
def test_mutabledisposable_replaceafterdispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() m.dispose() def action1(): disp1[0] = True d1 = Disposable.create(action1) m.disposable = d1 assert m.disposable == None assert disp1[0] def action2(): disp2[0] = True d2 = Disposable.create(action2) m.disposable = d2 assert m.disposable == None assert disp2[0]
class SchedulePeriodic(object): """Scheduler with support for running periodic tasks. This type of scheduler can be used to run timers more efficiently instead of using recursive scheduling.""" def __init__(self, scheduler, period, action, state=None): """ Keyword arguments: state -- Initial state passed to the action upon the first iteration. period -- Period for running the work periodically. action -- Action to be executed, potentially updating the state.""" self._scheduler = scheduler self._state = state self._period = period self._action = action self._cancel = SerialDisposable() def tick(self, scheduler, command): self._cancel.disposable = self._scheduler.schedule_relative( self._period, self.tick, 0) try: new_state = self._action(self._state) except Exception: self._cancel.dispose() raise else: if new_state is not None: # Update state if other than None self._state = new_state def start(self): """Returns the disposable object used to cancel the scheduled recurring action (best effort). """ self._cancel.disposable = self._scheduler.schedule_relative( self._period, self.tick, 0) return self._cancel
class SchedulePeriodic(object): """Scheduler with support for running periodic tasks. This type of scheduler can be used to run timers more efficiently instead of using recursive scheduling.""" def __init__(self, scheduler, period, action, state=None): """ Keyword arguments: state -- Initial state passed to the action upon the first iteration. period -- Period for running the work periodically. action -- Action to be executed, potentially updating the state.""" self._scheduler = scheduler self._state = state self._period = period self._action = action self._cancel = SerialDisposable() def tick(self, scheduler, command): self._cancel.disposable = self._scheduler.schedule_relative(self._period, self.tick, 0) try: new_state = self._action(self._state) except Exception: self._cancel.dispose() raise else: if new_state is not None: # Update state if other than None self._state = new_state def start(self): """Returns the disposable object used to cancel the scheduled recurring action (best effort). """ self._cancel.disposable = self._scheduler.schedule_relative(self._period, self.tick, 0) return self._cancel
class ScheduledObserver(ObserverBase): def __init__(self, scheduler, observer): super().__init__() self.scheduler = scheduler self.observer = observer self.lock = threading.RLock() self.is_acquired = False self.has_faulted = False self.queue = [] 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): def action(): self.observer.on_next(value) self.queue.append(action) def _on_error_core(self, error): def action(): self.observer.on_error(error) self.queue.append(action) def _on_completed_core(self): def action(): self.observer.on_completed() self.queue.append(action) def ensure_active(self): 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, state): 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): super().dispose() self.disposable.dispose()
class ScheduledObserver(AbstractObserver): def __init__(self, scheduler, observer): super(ScheduledObserver, self).__init__(self._next, self._error, self._completed) self.scheduler = scheduler self.observer = observer self.lock = Lock() self.is_acquired = False self.has_faulted = False self.queue = [] 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 _next(self, value): def action(): self.observer.on_next(value) self.queue.append(action) def _error(self, exception): def action(): self.observer.on_error(exception) self.queue.append(action) def _completed(self): def action(): self.observer.on_completed() self.queue.append(action) def ensure_active(self): is_owner = False with self.lock: if not self.has_faulted and len(self.queue): is_owner = not self.is_acquired self.is_acquired = True if is_owner: self.disposable.disposable = self.scheduler.schedule_recursive(self.run) def run(self, recurse, state): parent = self with self.lock: if len(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 recurse() def dispose(self): super(ScheduledObserver, self).dispose() self.disposable.dispose()
class ScheduledObserver(AbstractObserver): def __init__(self, scheduler, observer): super(ScheduledObserver, self).__init__(self._next, self._error, self._completed) self.scheduler = scheduler self.observer = observer self.lock = Lock() self.is_acquired = False self.has_faulted = False self.queue = [] 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 _next(self, value): def func(): self.observer.on_next(value) self.queue.append(func) def _error(self, exception): def func(): self.observer.on_error(exception) self.queue.append(func) def _completed(self): def func(): self.observer.on_completed() self.queue.append(func) def ensure_active(self): is_owner = False with self.lock: if not self.has_faulted and len(self.queue): is_owner = not self.is_acquired self.is_acquired = True if is_owner: self.disposable.disposable = self.scheduler.schedule_recursive( self.run) def run(self, recurse, state): parent = self with self.lock: if len(parent.queue): work = parent.queue.pop(0) else: parent.is_acquired = False return try: work() except Exception as ex: with self.lock: parent.queue = [] parent.has_faulted = True raise ex recurse() def dispose(self): super(ScheduledObserver, self).dispose() self.disposable.dispose()