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()
Beispiel #3
0
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
Beispiel #4
0
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_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
Beispiel #7
0
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]
Beispiel #8
0
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]
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
Beispiel #10
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
Beispiel #11
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
Beispiel #12
0
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()
Beispiel #13
0
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()
Beispiel #14
0
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()