def subscribe(observer, scheduler=None): is_open = [False] def on_next(left): if is_open[0]: observer.on_next(left) def on_completed(): if is_open[0]: observer.on_completed() subs = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) subscriptions = CompositeDisposable(subs) right_subscription = SingleAssignmentDisposable() subscriptions.add(right_subscription) def on_next2(x): is_open[0] = True right_subscription.dispose() def on_completed2(): right_subscription.dispose() right_subscription.disposable = other.subscribe_( on_next2, observer.on_error, on_completed2, scheduler) return subscriptions
def subscribe(observer, scheduler=None): group = CompositeDisposable() is_stopped = [False] m = SingleAssignmentDisposable() group.add(m) def on_next(inner_source): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = from_future(inner_source) if is_future(inner_source) else inner_source @synchronized(source.lock) def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() on_next = synchronized(source.lock)(observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription = inner_source.subscribe_(on_next, on_error, on_completed, scheduler) inner_subscription.disposable = subscription def on_completed(): is_stopped[0] = True if len(group) == 1: observer.on_completed() m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) return group
def test_groupdisposable_clear(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable(action1) def action2(): disp2[0] = True d2 = Disposable(action2) g = CompositeDisposable(d1, d2) assert g.length == 2 g.clear() assert disp1[0] assert disp2[0] assert not g.length disp3 = [False] def action3(): disp3[0] = True d3 = Disposable(action3) g.add(d3); assert not disp3[0] assert g.length == 1
def subscribe(observer, scheduler=None): window = [Subject()] d = CompositeDisposable() r = RefCountDisposable(d) observer.on_next(add_ref(window[0], r)) def on_next_window(x): window[0].on_next(x) def on_error(err): window[0].on_error(err) observer.on_error(err) def on_completed(): window[0].on_completed() observer.on_completed() d.add(source.subscribe_(on_next_window, on_error, on_completed, scheduler)) def on_next_observer(w): window[0].on_completed() window[0] = Subject() observer.on_next(add_ref(window[0], r)) d.add(window_boundaries.subscribe_(on_next_observer, on_error, on_completed, scheduler)) return r
def subscribe(observer, scheduler=None): was_invoked = [False] def on_completed(): observer.on_completed() try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) def on_error(exception): observer.on_error(exception) try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose(was_invoked)) subscription = source.subscribe_(observer.on_next, on_error, on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
def run(self): srcs = list(self.parent.sources) N = len(srcs) self.queues = [None] * N self.isDone = [False] * N self.subscriptions = [None] * N self.gate = RLock() for i in range(0, N): self.queues[i] = deque() # Loop twice because subscribing could already yield # a value before all queues are initialized for i in range(0, N): d = SingleAssignmentDisposable() self.subscriptions[i] = d o = self.O(self, i) d.disposable = srcs[i].subscribeSafe(o) c = CompositeDisposable(self.subscriptions) def dispose(): for q in self.queues: q.clear() c.add(Disposable.create(dispose)) return c
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or timeout_scheduler n = [0] s = [None] timer_d = SerialDisposable() window_id = [0] group_disposable = CompositeDisposable(timer_d) ref_count_disposable = RefCountDisposable(group_disposable) def create_timer(_id): m = SingleAssignmentDisposable() timer_d.disposable = m def action(scheduler, state): if _id != window_id[0]: return n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(new_id) m.disposable = _scheduler.schedule_relative(timespan, action) s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(0) def on_next(x): new_window = False new_id = 0 s[0].on_next(x) n[0] += 1 if n[0] == count: new_window = True n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) if new_window: create_timer(new_id) def on_error(e): s[0].on_error(e) observer.on_error(e) def on_completed(): s[0].on_completed() observer.on_completed() group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_)) return ref_count_disposable
def run(self): srcs = list(self.parent.sources) N = len(srcs) self.queues = [None] * N self.isDone = [False] * N self.subscriptions = [None] * N self.gate = RLock() for i in range(0, N): self.queues[i] = deque() # Loop twice because subscribing could already yield # a value before all queues are initialized for i in range(0, N): d = SingleAssignmentDisposable() self.subscriptions[i] = d o = self.O(self, i) d.disposable = srcs[i].subscribeSafe(o) c = CompositeDisposable(self.subscriptions) def dispose(): for q in self.queues: q.clear() c.add(Disposable.create(dispose)) return c
def subscribe(observer, scheduler=None): group = CompositeDisposable() is_stopped = [False] m = SingleAssignmentDisposable() group.add(m) def on_next(inner_source): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = from_future(inner_source) if is_future( inner_source) else inner_source @synchronized(source.lock) def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() on_next = synchronized(source.lock)(observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription = inner_source.subscribe_(on_next, on_error, on_completed, scheduler) inner_subscription.disposable = subscription def on_completed(): is_stopped[0] = True if len(group) == 1: observer.on_completed() m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) return group
def subscribe(observer, scheduler=None): window_subject = Subject() d = CompositeDisposable() r = RefCountDisposable(d) observer.on_next(add_ref(window_subject, r)) def on_next_window(x): window_subject.on_next(x) def on_error(err): window_subject.on_error(err) observer.on_error(err) def on_completed(): window_subject.on_completed() observer.on_completed() d.add( source.subscribe_(on_next_window, on_error, on_completed, scheduler)) def on_next_observer(w): nonlocal window_subject window_subject.on_completed() window_subject = Subject() observer.on_next(add_ref(window_subject, r)) d.add( boundaries.subscribe_(on_next_observer, on_error, on_completed, scheduler)) return r
def _subscribe_core(self, observer=None, scheduler=None) -> typing.Disposable: clock = self.scheduler.to_seconds(self.scheduler.now) self.subscriptions.append(Subscription(clock)) index = len(self.subscriptions) - 1 disp = CompositeDisposable() def get_action(notification): def action(scheduler, state): notification.accept(observer) return Disposable() return action for message in self.messages: notification = message.value # Don't make closures within a loop action = get_action(notification) disp.add(self.scheduler.schedule_relative(message.time, action)) def dispose() -> None: start = self.subscriptions[index].subscribe end = self.scheduler.to_seconds(self.scheduler.now) self.subscriptions[index] = Subscription(start, end) disp.dispose() return Disposable(dispose)
def subscribe(observer, scheduler=None): is_open = [False] def on_next(left): if is_open[0]: observer.on_next(left) def on_completed(): if is_open[0]: observer.on_completed() subs = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) subscriptions = CompositeDisposable(subs) right_subscription = SingleAssignmentDisposable() subscriptions.add(right_subscription) def on_next2(x): is_open[0] = True right_subscription.dispose() def on_completed2(): right_subscription.dispose() right_subscription.disposable = other.subscribe_(on_next2, observer.on_error, on_completed2, scheduler) return subscriptions
def subscribe(observer, scheduler=None): was_invoked = [False] def on_completed(): observer.on_completed() try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) def on_error(exception): observer.on_error(exception) try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose(was_invoked)) subscription = source.subscribe_(observer.on_next, on_error, on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() n = [0] s = [None] timer_d = SerialDisposable() window_id = [0] group_disposable = CompositeDisposable(timer_d) ref_count_disposable = RefCountDisposable(group_disposable) def create_timer(_id): m = SingleAssignmentDisposable() timer_d.disposable = m def action(scheduler, state): if _id != window_id[0]: return n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(new_id) m.disposable = _scheduler.schedule_relative(timespan, action) s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(0) def on_next(x): new_window = False new_id = 0 s[0].on_next(x) n[0] += 1 if n[0] == count: new_window = True n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) if new_window: create_timer(new_id) def on_error(e): s[0].on_error(e) observer.on_error(e) def on_completed(): s[0].on_completed() observer.on_completed() group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_)) return ref_count_disposable
def subscribe(observer, scheduler=None): composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose()) subscription = source.subscribe_(observer.on_next, observer.on_error, observer.on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
def test_groupdisposable_clear(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable(action1) def action2(): disp2[0] = True d2 = Disposable(action2) g = CompositeDisposable(d1, d2) assert g.length == 2 g.clear() assert disp1[0] assert disp2[0] assert not g.length disp3 = [False] def action3(): disp3[0] = True d3 = Disposable(action3) g.add(d3) assert not disp3[0] assert g.length == 1
def on_subscribe(observer, scheduler): def on_next(i): if type(i) is rs.OnNextMux: observer.on_next(i._replace(key=i.key[1])) elif type(i) is rs.OnErrorMux: observer.on_error(i.error) ''' elif type(i) is rs.OnCreateMux: observer.on_next(rs.OnCreateMux(i.key[1])) elif type(i) is rs.OnCompletedMux: observer.on_next(rs.OnCompletedMux(i.key[1])) else: observer.on_next(TypeError("flatten_aggregate: unknow item type: {}".format(type(i)))) ''' def on_next_outer(i): observer.on_next(i) disposable = CompositeDisposable() disposable.add( outer_group.subscribe( on_next=on_next_outer, scheduler=scheduler, )) disposable.add( source.subscribe( on_next=on_next, on_completed=observer.on_completed, on_error=observer.on_error, scheduler=scheduler, )) return disposable
def subscribe(observer, scheduler=None): accumulator_value = [seed] active = [False] group = CompositeDisposable() is_stopped = [False] queue = [] def subscribe(xs): subscription = SingleAssignmentDisposable() group.add(subscription) @synchronized(source.lock) def on_next(next_accumulator_value): accumulator_value[0] = next_accumulator_value observer.on_next(next_accumulator_value) @synchronized(source.lock) def on_completed(): group.remove(subscription) if queue: s = queue.pop(0) subscribe(s) else: active[0] = False if is_stopped[0]: observer.on_completed() on_error = synchronized(source.lock)(observer.on_error) subscription.disposable = xs.subscribe_( on_next, on_error, on_completed, scheduler) def on_next(value): def accumulate(): has_accumulator_value = accumulator_value[0] is not NotSet if has_accumulator_value: acc_source = accumulator(accumulator_value[0], value) return from_future(acc_source) if is_future( acc_source) else acc_source else: return of(value) accumulator_source = defer(lambda _: accumulate()) if not active[0]: active[0] = True subscribe(accumulator_source) else: queue.append(accumulator_source) def on_completed(): is_stopped[0] = True if not active[0]: observer.on_completed() group.add( source.subscribe_(on_next, observer.on_error, on_completed, scheduler)) return group
def test_groupdisposable_add(): d1 = Disposable() d2 = Disposable() g = CompositeDisposable(d1) assert g.length == 1 assert g.contains(d1) g.add(d2) assert g.length == 2 assert g.contains(d2)
def test_groupdisposable_add(): d1 = Disposable() d2 = Disposable() g = CompositeDisposable(d1) assert g.length == 1 assert g.contains(d1) g.add(d2) assert g.length == 2 assert g.contains(d2)
def observe(self, observer_info: MultiCastObserverInfo) -> rx.typing.Disposable: composite_disposable = CompositeDisposable() disposable = self.source.observe( init_observer_info(observer=FromFlowableMultiCastObserver( next_observer=observer_info.observer, subscriber=self.subscriber, composite_disposable=composite_disposable, ))) composite_disposable.add(disposable) return composite_disposable
def run(self): self.gate = RLock() groupDisposable = CompositeDisposable() self.refCountDisposable = RefCountDisposable(groupDisposable) self.createWindow() groupDisposable.add(self.parent.scheduler.schedulePeriodic(self.parent.timeSpan, self.tick)) groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
def observe(self, observer_info: ObserverInfo): composite_disposable = CompositeDisposable() disposable = self.source.observe( observer_info.copy(observer=FlatMergeNoBackpressureObserver( observer=observer_info.observer, selector=self.selector, scheduler=self.scheduler, subscribe_scheduler=self.subscribe_scheduler, composite_disposable=composite_disposable, ), )) composite_disposable.add(disposable) return composite_disposable
def run(self): self.gate = RLock() groupDisposable = CompositeDisposable() self.refCountDisposable = RefCountDisposable(groupDisposable) self.createWindow() groupDisposable.add( self.parent.scheduler.schedulePeriodic(self.parent.timeSpan, self.tick)) groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
def observe(self, observer_info: ObserverInfo): composite_disposable = CompositeDisposable() disposable = self.source.observe( observer_info.copy(observer=FlatMapObserver( observer_info=observer_info, func=self.func, scheduler=self.scheduler, subscribe_scheduler=self.subscribe_scheduler, composite_disposable=composite_disposable, )), ) composite_disposable.add(disposable) return composite_disposable
def run(self): self.gate = RLock() self.s = Subject() self.n = 0 self.windowId = 0 self.timerDisposable = SerialDisposable() groupDisposable = CompositeDisposable(self.timerDisposable) self.refCountDisposable = RefCountDisposable(groupDisposable) # AddRef was originally WindowObservable but this is just an alias for AddRef self.observer.onNext(AddRef(self.s, self.refCountDisposable)) self.createTimer(0) groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
def run(self): self.gate = RLock() self.s = Subject() self.n = 0 self.windowId = 0 self.timerDisposable = SerialDisposable() groupDisposable = CompositeDisposable(self.timerDisposable) self.refCountDisposable = RefCountDisposable(groupDisposable) # AddRef was originally WindowObservable but this is just an alias for AddRef self.observer.onNext(AddRef(self.s, self.refCountDisposable)) self.createTimer(0) groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
class RecursiveScheduledFunction(object): def __init__(self, action, scheduler, method = None): self.action = action self.group = CompositeDisposable() self.lock = RLock() if method == None: self.schedule = scheduler.scheduleWithState else: self.schedule = getattr(scheduler, method) def run(self, state): self.action(state, self.actionCallback) def actionCallback(self, newState, dueTime = None): self.isDone = False self.isAdded = False if dueTime == None: self.cancel = self.schedule( newState, self.schedulerCallback ) else: self.cancel = self.schedule( newState, dueTime, self.schedulerCallback ) with self.lock: if not self.isDone: self.group.add(self.cancel) self.isAdded = True def schedulerCallback(self, scheduler, state): with self.lock: if self.isAdded: self.group.remove(self.cancel) else: self.isDone = True self.run(state) return Disposable.empty()
def subscribe(observer, scheduler=None): m = SerialDisposable() d = CompositeDisposable(m) r = RefCountDisposable(d) window = Subject() observer.on_next(add_ref(window, r)) def on_next(value): window.on_next(value) def on_error(error): window.on_error(error) observer.on_error(error) def on_completed(): window.on_completed() observer.on_completed() d.add(source.subscribe_(on_next, on_error, on_completed, scheduler)) def create_window_on_completed(): try: window_close = closing_mapper() except Exception as exception: observer.on_error(exception) return def on_completed(): nonlocal window window.on_completed() window = Subject() observer.on_next(add_ref(window, r)) create_window_on_completed() m1 = SingleAssignmentDisposable() m.disposable = m1 m1.disposable = window_close.pipe(ops.take(1)).subscribe_( noop, on_error, on_completed, scheduler) create_window_on_completed() return r
def observe(self, observer_info: MultiCastObserverInfo) -> rx.typing.Disposable: group = CompositeDisposable() lock = threading.RLock() for inner_source in self.sources: inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) disposable = inner_source.observe(observer_info.copy( observer=MergeMultiCastObserver( observer=observer_info.observer, lock=lock, inner_subscription=inner_subscription, group=group ) )) inner_subscription.disposable = disposable return group
def run(self): self.totalTime = 0 self.nextShift = self.parent.timeShift self.nextSpan = self.parent.timeSpan self.gate = RLock() self.queue = deque() self.timerDisposable = SerialDisposable() groupDisposable = CompositeDisposable(self.timerDisposable) self.refCountDisposable = RefCountDisposable(groupDisposable) self.createWindow() self.createTimer() groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
def run(self): self.totalTime = 0 self.nextShift = self.parent.timeShift self.nextSpan = self.parent.timeSpan self.gate = RLock() self.queue = deque() self.timerDisposable = SerialDisposable() groupDisposable = CompositeDisposable(self.timerDisposable) self.refCountDisposable = RefCountDisposable(groupDisposable) self.createWindow() self.createTimer() groupDisposable.add(self.parent.source.subscribeSafe(self)) return self.refCountDisposable
def subscribe(observer, scheduler=None): active_count = [0] group = CompositeDisposable() is_stopped = [False] queue = [] def subscribe(xs): subscription = SingleAssignmentDisposable() group.add(subscription) @synchronized(source.lock) def on_completed(): group.remove(subscription) if queue: s = queue.pop(0) subscribe(s) else: active_count[0] -= 1 if is_stopped[0] and active_count[0] == 0: observer.on_completed() on_next = synchronized(source.lock)(observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription.disposable = xs.subscribe_( on_next, on_error, on_completed, scheduler) def on_next(inner_source): if active_count[0] < max_concurrent: active_count[0] += 1 subscribe(inner_source) else: queue.append(inner_source) def on_completed(): is_stopped[0] = True if active_count[0] == 0: observer.on_completed() group.add( source.subscribe_(on_next, observer.on_error, on_completed, scheduler)) return group
def subscribe(observer, scheduler=None): m = SerialDisposable() d = CompositeDisposable(m) r = RefCountDisposable(d) window = [Subject()] observer.on_next(add_ref(window[0], r)) def on_next(value): window[0].on_next(value) def on_error(error): window[0].on_error(error) observer.on_error(error) def on_completed(): window[0].on_completed() observer.on_completed() d.add(source.subscribe_(on_next, on_error, on_completed, scheduler)) def create_window_on_completed(): try: window_close = window_closing_mapper() except Exception as exception: observer.on_error(exception) return def on_completed(): window[0].on_completed() window[0] = Subject() observer.on_next(add_ref(window[0], r)) create_window_on_completed() m1 = SingleAssignmentDisposable() m.disposable = m1 m1.disposable = window_close.pipe(ops.take(1)).subscribe_(noop, on_error, on_completed, scheduler) create_window_on_completed() return r
def subscribe(observer, scheduler=None): active_count = [0] group = CompositeDisposable() is_stopped = [False] queue = [] def subscribe(xs): subscription = SingleAssignmentDisposable() group.add(subscription) @synchronized(source.lock) def on_completed(): group.remove(subscription) if queue: s = queue.pop(0) subscribe(s) else: active_count[0] -= 1 if is_stopped[0] and active_count[0] == 0: observer.on_completed() on_next = synchronized(source.lock)(observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription.disposable = xs.subscribe_(on_next, on_error, on_completed, scheduler) def on_next(inner_source): if active_count[0] < max_concurrent: active_count[0] += 1 subscribe(inner_source) else: queue.append(inner_source) def on_completed(): is_stopped[0] = True if active_count[0] == 0: observer.on_completed() group.add(source.subscribe_(on_next, observer.on_error, on_completed, scheduler)) return group
def test_groupdisposable_addafterdispose(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable(action1) def action2(): disp2[0] = True d2 = Disposable(action2) g = CompositeDisposable(d1) assert g.length == 1 g.dispose() assert disp1[0] assert g.length == 0 g.add(d2) assert disp2[0] assert g.length == 0
class RecursiveScheduledFunction(object): def __init__(self, action, scheduler, method=None): self.action = action self.group = CompositeDisposable() self.lock = RLock() if method == None: self.schedule = scheduler.scheduleWithState else: self.schedule = getattr(scheduler, method) def run(self, state): self.action(state, self.actionCallback) def actionCallback(self, newState, dueTime=None): self.isDone = False self.isAdded = False if dueTime == None: self.cancel = self.schedule(newState, self.schedulerCallback) else: self.cancel = self.schedule(newState, dueTime, self.schedulerCallback) with self.lock: if not self.isDone: self.group.add(self.cancel) self.isAdded = True def schedulerCallback(self, scheduler, state): with self.lock: if self.isAdded: self.group.remove(self.cancel) else: self.isDone = True self.run(state) return Disposable.empty()
def test_groupdisposable_addafterdispose(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable(action1) def action2(): disp2[0] = True d2 = Disposable(action2) g = CompositeDisposable(d1) assert g.length == 1 g.dispose() assert disp1[0] assert g.length == 0 g.add(d2) assert disp2[0] assert g.length == 0
def subscribe(self, single: Single): group = CompositeDisposable() m = SingleAssignmentDisposable() group.add(m) lock = threading.RLock() class MergeAllSingle(Single): # def on_error(self, exc: Exception): # single.on_error(exc) def on_next(_, inner_source: Ack): class ResultSingle(Single): def on_next(self, elem): single.on_next(elem) # def on_error(self, exc: Exception): # single.on_error(exc) disposable = inner_source.subscribe(ResultSingle()) group.add(disposable) m.disposable = source.subscribe(MergeAllSingle()) return group
def subscribe(observer, scheduler=None): has_current = [False] is_stopped = [False] m = SingleAssignmentDisposable() g = CompositeDisposable() g.add(m) def on_next(inner_source): if not has_current[0]: has_current[0] = True inner_source = rx.from_future(inner_source) if is_future(inner_source) else inner_source inner_subscription = SingleAssignmentDisposable() g.add(inner_subscription) def on_completed_inner(): g.remove(inner_subscription) has_current[0] = False if is_stopped[0] and len(g) == 1: observer.on_completed() inner_subscription.disposable = inner_source.subscribe_( observer.on_next, observer.on_error, on_completed_inner, scheduler ) def on_completed(): is_stopped[0] = True if not has_current[0] and len(g) == 1: observer.on_completed() m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) return g
def subscribe(observer, scheduler=None): has_current = [False] is_stopped = [False] m = SingleAssignmentDisposable() g = CompositeDisposable() g.add(m) def on_next(inner_source): if not has_current[0]: has_current[0] = True inner_source = rx.from_future(inner_source) if is_future( inner_source) else inner_source inner_subscription = SingleAssignmentDisposable() g.add(inner_subscription) def on_completed_inner(): g.remove(inner_subscription) has_current[0] = False if is_stopped[0] and len(g) == 1: observer.on_completed() inner_subscription.disposable = inner_source.subscribe_( observer.on_next, observer.on_error, on_completed_inner, scheduler) def on_completed(): is_stopped[0] = True if not has_current[0] and len(g) == 1: observer.on_completed() m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) return g
class Bus(Generic[T], Closeable, ABC): def __init__(self, serial: Serial, scanner: BusScanner) -> None: super().__init__() self.__serial = serial self.__scanner = scanner self.__added_devices: Subject[Device[T]] = Subject() self.__device_list: List[Device[T]] = list() self.__disposable = CompositeDisposable() self.__disposable.add(self.__added_devices) self.__disposable.add(self.__scanner.scan().subscribe( on_next=self.__add_device, on_error=self.close, scheduler=NewThreadScheduler())) def __add_device(self, device: Device[T]) -> None: assert device not in self.__device_list self.__device_list.append(device) self.__added_devices.on_next(device) self.__disposable.add(device.on_close().subscribe( lambda _: self.__remove_device(device))) def __remove_device(self, device: Device[T]) -> None: self.__device_list.remove(device) def close(self, reason: str = None) -> None: super().close(reason) self.__disposable.dispose() for device in self.__device_list: device.close(reason) def get_devices(self) -> Observable: return rx.concat(rx.from_list(self.__device_list), self.__added_devices) @property def serial(self) -> Serial: return self.__serial
def subscribe(observer, scheduler=None): group = CompositeDisposable() left_done = [False] left_map = OrderedDict() left_id = [0] right_done = [False] right_map = OrderedDict() right_id = [0] def on_next_left(value): duration = None current_id = left_id[0] left_id[0] += 1 md = SingleAssignmentDisposable() left_map[current_id] = value group.add(md) def expire(): if current_id in left_map: del left_map[current_id] if not len(left_map) and left_done[0]: observer.on_completed() return group.remove(md) try: duration = left_duration_mapper(value) except Exception as exception: observer.on_error(exception) return md.disposable = duration.pipe(take(1)).subscribe_(noop, observer.on_error, lambda: expire(), scheduler) for val in right_map.values(): result = (value, val) observer.on_next(result) def on_completed_left(): left_done[0] = True if right_done[0] or not len(left_map): observer.on_completed() group.add(left.subscribe_(on_next_left, observer.on_error, on_completed_left, scheduler)) def on_next_right(value): duration = None current_id = right_id[0] right_id[0] += 1 md = SingleAssignmentDisposable() right_map[current_id] = value group.add(md) def expire(): if current_id in right_map: del right_map[current_id] if not len(right_map) and right_done[0]: observer.on_completed() return group.remove(md) try: duration = right_duration_mapper(value) except Exception as exception: observer.on_error(exception) return md.disposable = duration.pipe(take(1)).subscribe_(noop, observer.on_error, lambda: expire(), scheduler) for val in left_map.values(): result = (val, value) observer.on_next(result) def on_completed_right(): right_done[0] = True if left_done[0] or not len(right_map): observer.on_completed() group.add(right.subscribe_(on_next_right, observer.on_error, on_completed_right)) return group
class GroupBy(Producer): def __init__(self, source, keySelector, elementSelector): self.source = source self.keySelector = keySelector self.elementSelector = elementSelector def run(self, observer, cancel, setSink): self.groupDisposable = CompositeDisposable() self.refCountDisposable = RefCountDisposable(self.groupDisposable) sink = self.Sink(self, observer, cancel) setSink(sink) self.groupDisposable.add(self.source.subscribeSafe(sink)) return self.refCountDisposable class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(GroupBy.Sink, self).__init__(observer, cancel) self.parent = parent self.map = {} self.null = None def onNext(self, value): key = None try: key = self.parent.keySelector(value) except Exception as e: self.onError(e) return fireNewMapEntry = False writer = None try: if key == None: if self.null == None: self.null = Subject() fireNewMapEntry = True writer = self.null else: if key in self.map: writer = self.map[key] else: writer = Subject() self.map[key] = writer fireNewMapEntry = True except Exception as e: self.onError(e) return if fireNewMapEntry: group = GroupObservable(key, writer, self.parent.refCountDisposable) self.observer.onNext(group) element = None try: element = self.parent.elementSelector(value) except Exception as e: self.onError(e) else: writer.onNext(element) def onError(self, exception): if self.null != None: self.null.onError(exception) for x in self.map.values(): x.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): if self.null != None: self.null.onCompleted() for x in self.map.values(): x.onCompleted() self.observer.onCompleted() self.dispose()
class GroupBy(Producer): def __init__(self, source, keySelector, elementSelector): self.source = source self.keySelector = keySelector self.elementSelector = elementSelector def run(self, observer, cancel, setSink): self.groupDisposable = CompositeDisposable() self.refCountDisposable = RefCountDisposable(self.groupDisposable) sink = self.Sink(self, observer, cancel) setSink(sink) self.groupDisposable.add(self.source.subscribeSafe(sink)) return self.refCountDisposable class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(GroupBy.Sink, self).__init__(observer, cancel) self.parent = parent self.map = {} self.null = None def onNext(self, value): key = None try: key = self.parent.keySelector(value) except Exception as e: self.onError(e) return fireNewMapEntry = False writer = None try: if key == None: if self.null == None: self.null = Subject() fireNewMapEntry = True writer = self.null else: if key in self.map: writer = self.map[key] else: writer = Subject() self.map[key] = writer fireNewMapEntry = True except Exception as e: self.onError(e) return if fireNewMapEntry: group = GroupObservable(key, writer, self.parent.refCountDisposable) self.observer.onNext(group) element = None try: element = self.parent.elementSelector(value) except Exception as e: self.onError(e) else: writer.onNext(element) def onError(self, exception): if self.null != None: self.null.onError(exception) for x in self.map.values(): x.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): if self.null != None: self.null.onCompleted() for x in self.map.values(): x.onCompleted() self.observer.onCompleted() self.dispose()
class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(DelayObservable.Sink, self).__init__(observer, cancel) self.parent = parent def run(self): self.delays = CompositeDisposable() self.gate = RLock() self.atEnd = False self.subscription = SerialDisposable() if self.parent.subscriptionDelay == None: self.start() else: self.subscription.disposable = self.parent.subscriptionDelay.subscribeSafe(self.Sigma(self)) return CompositeDisposable(self.subscription, self.delays) def start(self): self.subscription.disposable = self.parent.source.subscribeSafe(self) def onNext(self, value): try: delay = self.parent.delaySelector(value) except Exception as e: with self.gate: self.observer.onError(e) self.dispose() else: d = SingleAssignmentDisposable() self.delays.add(d) d.disposable = delay.subscribeSafe(self.Delta(self, value, d)) def onError(self, exception): with self.gate: self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.atEnd = True self.subscription.dispose() self.checkDone() def checkDone(self): if self.atEnd and self.delays.length == 0: self.observer.onCompleted() self.dispose() class Sigma(Observer): def __init__(self, parent): self.parent = parent def onNext(self, value): self.parent.start() def onError(self, exception): self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): self.parent.start() class Delta(Observer): def __init__(self, parent, value, cancelSelf): self.parent = parent self.value = value self.cancelSelf = cancelSelf def onNext(self, delay): with self.parent.gate: self.parent.observer.onNext(self.value) self.parent.delays.remove(self.cancelSelf) self.parent.checkDone() def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.observer.onNext(self.value) self.parent.delays.remove(self.cancelSelf) self.parent.checkDone()
def subscribe(observer, scheduler=None): group = CompositeDisposable() rcd = RefCountDisposable(group) left_map = OrderedDict() right_map = OrderedDict() left_id = [0] right_id = [0] def on_next_left(value): subject = Subject() with left.lock: _id = left_id[0] left_id[0] += 1 left_map[_id] = subject try: result = (value, add_ref(subject, rcd)) except Exception as e: log.error("*** Exception: %s" % e) for left_value in left_map.values(): left_value.on_error(e) observer.on_error(e) return observer.on_next(result) for right_value in right_map.values(): subject.on_next(right_value) md = SingleAssignmentDisposable() group.add(md) def expire(): if _id in left_map: del left_map[_id] subject.on_completed() group.remove(md) try: duration = left_duration_mapper(value) except Exception as e: for left_value in left_map.values(): left_value.on_error(e) observer.on_error(e) return def on_error(error): for left_value in left_map.values(): left_value.on_error(error) observer.on_error(error) md.disposable = duration.pipe(ops.take(1)).subscribe_(nothing, on_error, expire, scheduler) def on_error_left(error): for left_value in left_map.values(): left_value.on_error(error) observer.on_error(error) group.add(left.subscribe_(on_next_left, on_error_left, observer.on_completed, scheduler)) def send_right(value): with left.lock: _id = right_id[0] right_id[0] += 1 right_map[_id] = value md = SingleAssignmentDisposable() group.add(md) def expire(): del right_map[_id] group.remove(md) try: duration = right_duration_mapper(value) except Exception as e: for left_value in left_map.values(): left_value.on_error(e) observer.on_error(e) return def on_error(error): with left.lock: for left_value in left_map.values(): left_value.on_error(error) observer.on_error(error) md.disposable = duration.pipe(ops.take(1)).subscribe_(nothing, on_error, expire, scheduler) with left.lock: for left_value in left_map.values(): left_value.on_next(value) def on_error_right(error): for left_value in left_map.values(): left_value.on_error(error) observer.on_error(error) group.add(right.subscribe_(send_right, on_error_right, scheduler=scheduler)) return rcd
def subscribe(observer, scheduler=None): writers = OrderedDict() group_disposable = CompositeDisposable() ref_count_disposable = RefCountDisposable(group_disposable) def on_next(x): writer = None key = None try: key = key_mapper(x) except Exception as e: for wrt in writers.values(): wrt.on_error(e) observer.on_error(e) return fire_new_map_entry = False writer = writers.get(key) if not writer: writer = Subject() writers[key] = writer fire_new_map_entry = True if fire_new_map_entry: group = GroupedObservable(key, writer, ref_count_disposable) duration_group = GroupedObservable(key, writer) try: duration = duration_mapper(duration_group) except Exception as e: for wrt in writers.values(): wrt.on_error(e) observer.on_error(e) return observer.on_next(group) sad = SingleAssignmentDisposable() group_disposable.add(sad) def expire(): if writers[key]: del writers[key] writer.on_completed() group_disposable.remove(sad) def on_next(value): pass def on_error(exn): for wrt in writers.values(): wrt.on_error(exn) observer.on_error(exn) def on_completed(): expire() sad.disposable = duration.pipe(ops.take(1)).subscribe_(on_next, on_error, on_completed, scheduler) try: element = element_mapper(x) except Exception as error: for wrt in writers.values(): wrt.on_error(error) observer.on_error(error) return writer.on_next(element) def on_error(ex): for wrt in writers.values(): wrt.on_error(ex) observer.on_error(ex) def on_completed(): for wrt in writers.values(): wrt.on_completed() observer.on_completed() group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler)) return ref_count_disposable
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or timeout_scheduler timer_d = SerialDisposable() next_shift = [timeshift] next_span = [timespan] total_time = [DELTA_ZERO] q = [] group_disposable = CompositeDisposable(timer_d) ref_count_disposable = RefCountDisposable(group_disposable) def create_timer(): m = SingleAssignmentDisposable() timer_d.disposable = m is_span = False is_shift = False if next_span[0] == next_shift[0]: is_span = True is_shift = True elif next_span[0] < next_shift[0]: is_span = True else: is_shift = True new_total_time = next_span[0] if is_span else next_shift[0] ts = new_total_time - total_time[0] total_time[0] = new_total_time if is_span: next_span[0] += timeshift if is_shift: next_shift[0] += timeshift def action(scheduler, state=None): s = None if is_shift: s = Subject() q.append(s) observer.on_next(add_ref(s, ref_count_disposable)) if is_span: s = q.pop(0) s.on_completed() create_timer() m.disposable = _scheduler.schedule_relative(ts, action) q.append(Subject()) observer.on_next(add_ref(q[0], ref_count_disposable)) create_timer() def on_next(x): for s in q: s.on_next(x) def on_error(e): for s in q: s.on_error(e) observer.on_error(e) def on_completed(): for s in q: s.on_completed() observer.on_completed() group_disposable.add( source.subscribe_(on_next, on_error, on_completed, scheduler_)) return ref_count_disposable
class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(GroupJoin.Sink, self).__init__(observer, cancel) self.parent = parent def run(self): self.gate = RLock() self.group = CompositeDisposable() self.refCount = RefCountDisposable(self.group) leftSubscription = SingleAssignmentDisposable() self.group.add(leftSubscription) self.leftID = 0 self.leftMap = {} rightSubscription = SingleAssignmentDisposable() self.group.add(rightSubscription) self.rightID = 0 self.rightMap = {} leftSubscription.disposable = self.parent.left.subscribeSafe(self.Left(self, leftSubscription)) rightSubscription.disposable = self.parent.right.subscribeSafe(self.Right(self, rightSubscription)) return self.refCount class Left(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, group, resource): with self.parent.gate: if resourceId in self.parent.leftMap: del self.parent.leftMap[resourceId] group.onCompleted() self.parent.group.remove(resource) def onNext(self, value): s = Subject() resourceId = 0 with self.parent.gate: self.parent.leftID += 1 resourceId = self.parent.leftID self.parent.leftMap[resourceId] = s # AddRef was originally WindowObservable but this is just an alias for AddRef window = AddRef(s, self.parent.refCount) md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.leftDurationSelector(value) except Exception as e: self.onError(e) return else: md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, s, md)) try: result = self.parent.parent.resultSelector(value, window) except Exception as e: self.onError(e) return else: with self.parent.gate: self.parent.observer.onNext(result) for rightValue in self.parent.rightMap.values(): s.onNext(rightValue) def onError(self, exception): with self.parent.gate: for o in self.parent.leftMap.values(): o.onError(exception) self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.observer.onCompleted() self.parent.dispose() self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, group, resource): self.parent = parent self.resourceId = resourceId self.group = group self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.group, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.group, self.resource) #end Delta #end Left class Right(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, resource): with self.parent.gate: self.parent.rightMap.pop(resourceId, None) self.parent.group.remove(resource) def onNext(self, value): resourceId = 0 with self.parent.gate: self.parent.rightID += 1 resourceId = self.parent.rightID self.parent.rightMap[resourceId] = value md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.rightDurationSelector(value) except Exception as e: self.onError(e) return else: md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md)) with self.parent.gate: for o in self.parent.leftMap.values(): o.onNext(value) def onError(self, exception): with self.parent.gate: for o in self.parent.leftMap.values(): o.onError(exception) self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, resource): self.parent = parent self.resourceId = resourceId self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.resource)
def subscribe(observer, scheduler=None): group = CompositeDisposable() left_done = False left_map = OrderedDict() left_id = 0 right_done = False right_map = OrderedDict() right_id = 0 def on_next_left(value): nonlocal left_id duration = None current_id = left_id left_id += 1 md = SingleAssignmentDisposable() left_map[current_id] = value group.add(md) def expire(): if current_id in left_map: del left_map[current_id] if not len(left_map) and left_done: observer.on_completed() return group.remove(md) try: duration = left_duration_mapper(value) except Exception as exception: observer.on_error(exception) return md.disposable = duration.pipe(take(1)).subscribe_( noop, observer.on_error, lambda: expire(), scheduler) for val in right_map.values(): result = (value, val) observer.on_next(result) def on_completed_left(): nonlocal left_done left_done = True if right_done or not len(left_map): observer.on_completed() group.add( left.subscribe_(on_next_left, observer.on_error, on_completed_left, scheduler)) def on_next_right(value): nonlocal right_id duration = None current_id = right_id right_id += 1 md = SingleAssignmentDisposable() right_map[current_id] = value group.add(md) def expire(): if current_id in right_map: del right_map[current_id] if not len(right_map) and right_done: observer.on_completed() return group.remove(md) try: duration = right_duration_mapper(value) except Exception as exception: observer.on_error(exception) return md.disposable = duration.pipe(take(1)).subscribe_( noop, observer.on_error, lambda: expire(), scheduler) for val in left_map.values(): result = (val, value) observer.on_next(result) def on_completed_right(): nonlocal right_done right_done = True if left_done or not len(right_map): observer.on_completed() group.add( right.subscribe_(on_next_right, observer.on_error, on_completed_right, scheduler)) return group
class GroupByUntil(Producer): def __init__(self, source, keySelector, elementSelector, durationSelector): self.source = source self.keySelector = keySelector self.elementSelector = elementSelector self.durationSelector = durationSelector def run(self, observer, cancel, setSink): self.groupDisposable = CompositeDisposable() self.refCountDisposable = RefCountDisposable(self.groupDisposable) sink = self.Sink(self, observer, cancel) setSink(sink) self.groupDisposable.add(self.source.subscribeSafe(sink)) return self.refCountDisposable class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(GroupByUntil.Sink, self).__init__(observer, cancel) self.parent = parent self.map = {} self.null = None self.nullGate = RLock() self.nullGateForDeltas = RLock() self.observerGate = RLock() self.writerGate = RLock() def onNext(self, value): key = None try: key = self.parent.keySelector(value) except Exception as e: self.onError(e) return fireNewMapEntry = False writer = None try: if key == None: with self.nullGate: if self.null == None: self.null = Subject() fireNewMapEntry = True writer = self.null else: if key in self.map: writer = self.map[key] else: writer = Subject() self.map[key] = writer fireNewMapEntry = True except Exception as e: self.onError(e) return if fireNewMapEntry: group = GroupObservable(key, writer, self.parent.refCountDisposable) duration = None durationGroup = GroupObservable(key, writer) try: duration = self.parent.durationSelector(durationGroup) except Exception as e: self.onError(e) return with self.observerGate: self.observer.onNext(group) md = SingleAssignmentDisposable() self.parent.groupDisposable.add(md) md.disposable = duration.subscribeSafe(self.Delta(self, key, writer, md)) element = None try: element = self.parent.elementSelector(value) except Exception as e: self.onError(e) else: with self.writerGate: writer.onNext(element) def onError(self, exception): # # NOTE: A race with OnCompleted triggered by a duration selector is fine when # using Subject<T>. It will transition into a terminal state, making one # of the two calls a no-op by swapping in a DoneObserver<T>. # null = None with self.nullGate: null = self.null if null != None: null.onError(exception) for x in self.map.values(): x.onError(exception) with self.observerGate: self.observer.onError(exception) self.dispose() def onCompleted(self): # # NOTE: A race with OnCompleted triggered by a duration selector is fine when # using Subject<T>. It will transition into a terminal state, making one # of the two calls a no-op by swapping in a DoneObserver<T>. # null = None with self.nullGate: null = self.null if null != None: null.onCompleted() for x in self.map.values(): x.onCompleted() with self.observerGate: self.observer.onCompleted() self.dispose() class Delta(Observer): def __init__(self, parent, key, writer, cancelSelf): self.parent = parent self.key = key self.writer = writer self.cancelSelf = cancelSelf def onNext(self, value): self.onCompleted() def onError(self, exception): self.parent.onError(exception) self.cancelSelf.dispose() def onCompleted(self): if self.key == None: null = None with self.parent.nullGate: null = self.parent.null self.parent.null = None with self.parent.nullGateForDeltas: null.onCompleted() else: try: del self.parent.map[self.key] except KeyError: pass else: with self.parent.writerGate: self.writer.onCompleted() self.parent.parent.groupDisposable.remove(self.cancelSelf)
class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(SelectMany.Sink, self).__init__(observer, cancel) self.parent = parent self.index = -1 def run(self): self.gate = RLock() self.isStopped = False self.group = CompositeDisposable() self.sourceSubscription = SingleAssignmentDisposable() self.group.add(self.sourceSubscription) self.sourceSubscription.disposable = self.parent.source.subscribeSafe(self) return self.group def onNext(self, value): inner = None try: if self.parent.withIndex: self.index += 1 inner = self.parent.selectorOnNext(value, self.index) else: inner = self.parent.selectorOnNext(value) except Exception as e: with self.gate: self.observer.onError(e) self.dispose() if isinstance(inner, Observable): self.subscribeInner(inner) return # iterable try: for current in inner: self.observer.onNext(current) except Exception as e: self.observer.onError(e) self.dispose() def onError(self, exception): if self.parent.selectorOnError != None: try: inner = None if self.parent.withIndex: self.index += 1 inner = self.parent.selectorOnError(exception, self.index) else: inner = self.parent.selectorOnError(exception) except Exception as e: with self.gate: self.observer.onError(e) self.dispose() else: self.subscribeInner(inner) self.final() else: with self.gate: self.observer.onError(exception) self.dispose() def onCompleted(self): if self.parent.selectorOnCompleted != None: try: inner = None if self.parent.withIndex: inner = self.parent.selectorOnCompleted(self.index) else: inner = self.parent.selectorOnCompleted() except Exception as e: with self.gate: self.observer.onError(e) self.dispose() return else: self.subscribeInner(inner) self.final() def final(self): self.isStopped = True if self.group.length == 1: # # Notice there can be a race between OnCompleted of the source and any # of the inner sequences, where both see _group.Count == 1, and one is # waiting for the lock. There won't be a double OnCompleted observation # though, because the call to Dispose silences the observer by swapping # in a NopObserver<T>. # with self.gate: self.observer.onCompleted() self.dispose() else: self.sourceSubscription.dispose() def subscribeInner(self, inner): innerSubscription = SingleAssignmentDisposable() self.group.add(innerSubscription) innerSubscription.disposable = inner.subscribeSafe(self.LockingObserver(self, innerSubscription)) class LockingObserver(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def onNext(self, value): with self.parent.gate: self.parent.observer.onNext(value) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): self.parent.group.remove(self.subscription) if self.parent.isStopped and self.parent.group.length == 1: # # Notice there can be a race between OnCompleted of the source and any # of the inner sequences, where both see _group.Count == 1, and one is # waiting for the lock. There won't be a double OnCompleted observation # though, because the call to Dispose silences the observer by swapping # in a NopObserver<T>. # with self.parent.gate: self.parent.observer.onCompleted() self.parent.dispose()
def subscribe(observer, scheduler=None): composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose()) subscription = source.subscribe_(observer.on_next, observer.on_error, observer.on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or timeout_scheduler timer_d = SerialDisposable() next_shift = [timeshift] next_span = [timespan] total_time = [DELTA_ZERO] q = [] group_disposable = CompositeDisposable(timer_d) ref_count_disposable = RefCountDisposable(group_disposable) def create_timer(): m = SingleAssignmentDisposable() timer_d.disposable = m is_span = False is_shift = False if next_span[0] == next_shift[0]: is_span = True is_shift = True elif next_span[0] < next_shift[0]: is_span = True else: is_shift = True new_total_time = next_span[0] if is_span else next_shift[0] ts = new_total_time - total_time[0] total_time[0] = new_total_time if is_span: next_span[0] += timeshift if is_shift: next_shift[0] += timeshift def action(scheduler, state=None): s = None if is_shift: s = Subject() q.append(s) observer.on_next(add_ref(s, ref_count_disposable)) if is_span: s = q.pop(0) s.on_completed() create_timer() m.disposable = _scheduler.schedule_relative(ts, action) q.append(Subject()) observer.on_next(add_ref(q[0], ref_count_disposable)) create_timer() def on_next(x): for s in q: s.on_next(x) def on_error(e): for s in q: s.on_error(e) observer.on_error(e) def on_completed(): for s in q: s.on_completed() observer.on_completed() group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_)) return ref_count_disposable
class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Join.Sink, self).__init__(observer, cancel) self.parent = parent def run(self): self.gate = RLock() self.group = CompositeDisposable() self.refCount = RefCountDisposable(self.group) leftSubscription = SingleAssignmentDisposable() self.group.add(leftSubscription) self.leftDone = False self.leftID = 0 self.leftMap = {} rightSubscription = SingleAssignmentDisposable() self.group.add(rightSubscription) self.rightDone = False self.rightID = 0 self.rightMap = {} leftSubscription.disposable = self.parent.left.subscribeSafe(self.Lambda(self, leftSubscription)) rightSubscription.disposable = self.parent.right.subscribeSafe(self.Roh(self, rightSubscription)) return self.refCount class Lambda(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, resource): with self.parent.gate: if resourceId in self.parent.leftMap: del self.parent.leftMap[resourceId] if len(self.parent.leftMap) == 0 and self.parent.leftDone: self.parent.observer.onCompleted() self.parent.dispose() self.parent.group.remove(resource) def onNext(self, value): resourceId = 0 with self.parent.gate: self.parent.leftID += 1 resourceId = self.parent.leftID self.parent.leftMap[resourceId] = value # AddRef was originally WindowObservable but this is just an alias for AddRef md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.leftDurationSelector(value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md)) with self.parent.gate: for rightValue in self.parent.rightMap.values(): try: result = self.parent.parent.resultSelector(value, rightValue) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: self.parent.observer.onNext(result) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.leftDone = True if self.parent.rightDone or len(self.parent.leftMap) == 0: self.parent.observer.onCompleted() self.parent.dispose() else: self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, resource): self.parent = parent self.resourceId = resourceId self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.resource) #end Delta #end Lambda class Roh(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, resource): with self.parent.gate: if resourceId in self.parent.rightMap: del self.parent.rightMap[resourceId] if len(self.parent.rightMap) == 0 and self.parent.rightDone: self.parent.observer.onCompleted() self.parent.dispose() self.parent.group.remove(resource) def onNext(self, value): resourceId = 0 with self.parent.gate: self.parent.rightID += 1 resourceId = self.parent.rightID self.parent.rightMap[resourceId] = value # AddRef was originally WindowObservable but this is just an alias for AddRef md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.rightDurationSelector(value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: md.disposable = duration.subscribeSafe(self.Delta(self, resourceId, md)) with self.parent.gate: for leftValue in self.parent.leftMap.values(): try: result = self.parent.parent.resultSelector(leftValue, value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: self.parent.observer.onNext(result) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.rightDone = True if self.parent.leftDone or len(self.parent.rightMap) == 0: self.parent.observer.onCompleted() self.parent.dispose() else: self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, resource): self.parent = parent self.resourceId = resourceId self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.resource) #end Roh #end Sink #end Join
class Sink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Join.Sink, self).__init__(observer, cancel) self.parent = parent def run(self): self.gate = RLock() self.group = CompositeDisposable() self.refCount = RefCountDisposable(self.group) leftSubscription = SingleAssignmentDisposable() self.group.add(leftSubscription) self.leftDone = False self.leftID = 0 self.leftMap = {} rightSubscription = SingleAssignmentDisposable() self.group.add(rightSubscription) self.rightDone = False self.rightID = 0 self.rightMap = {} leftSubscription.disposable = self.parent.left.subscribeSafe( self.Lambda(self, leftSubscription)) rightSubscription.disposable = self.parent.right.subscribeSafe( self.Roh(self, rightSubscription)) return self.refCount class Lambda(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, resource): with self.parent.gate: if resourceId in self.parent.leftMap: del self.parent.leftMap[resourceId] if len(self.parent.leftMap ) == 0 and self.parent.leftDone: self.parent.observer.onCompleted() self.parent.dispose() self.parent.group.remove(resource) def onNext(self, value): resourceId = 0 with self.parent.gate: self.parent.leftID += 1 resourceId = self.parent.leftID self.parent.leftMap[resourceId] = value # AddRef was originally WindowObservable but this is just an alias for AddRef md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.leftDurationSelector(value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: md.disposable = duration.subscribeSafe( self.Delta(self, resourceId, md)) with self.parent.gate: for rightValue in self.parent.rightMap.values(): try: result = self.parent.parent.resultSelector( value, rightValue) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: self.parent.observer.onNext(result) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.leftDone = True if self.parent.rightDone or len(self.parent.leftMap) == 0: self.parent.observer.onCompleted() self.parent.dispose() else: self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, resource): self.parent = parent self.resourceId = resourceId self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.resource) #end Delta #end Lambda class Roh(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def expire(self, resourceId, resource): with self.parent.gate: if resourceId in self.parent.rightMap: del self.parent.rightMap[resourceId] if len(self.parent.rightMap ) == 0 and self.parent.rightDone: self.parent.observer.onCompleted() self.parent.dispose() self.parent.group.remove(resource) def onNext(self, value): resourceId = 0 with self.parent.gate: self.parent.rightID += 1 resourceId = self.parent.rightID self.parent.rightMap[resourceId] = value # AddRef was originally WindowObservable but this is just an alias for AddRef md = SingleAssignmentDisposable() self.parent.group.add(md) try: duration = self.parent.parent.rightDurationSelector(value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: md.disposable = duration.subscribeSafe( self.Delta(self, resourceId, md)) with self.parent.gate: for leftValue in self.parent.leftMap.values(): try: result = self.parent.parent.resultSelector( leftValue, value) except Exception as e: self.parent.observer.onError(e) self.parent.dispose() return else: self.parent.observer.onNext(result) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): with self.parent.gate: self.parent.rightDone = True if self.parent.leftDone or len(self.parent.rightMap) == 0: self.parent.observer.onCompleted() self.parent.dispose() else: self.dispose() class Delta(Observer): """Expires parent on Next or Completed""" def __init__(self, parent, resourceId, resource): self.parent = parent self.resourceId = resourceId self.resource = resource def onNext(self, value): self.parent.expire(self.resourceId, self.resource) def onError(self, exception): self.parent.onError(exception) def onCompleted(self): self.parent.expire(self.resourceId, self.resource) #end Roh #end Sink #end Join
class ConcurrentSink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Merge.ConcurrentSink, self).__init__(observer, cancel) self.parent = parent def run(self): self.gate = RLock() self.q = Queue() self.isStopped = False self.activeCount = 0 self.group = CompositeDisposable() self.sourceSubscription = SingleAssignmentDisposable() self.group.add(self.sourceSubscription) self.sourceSubscription.disposable = self.parent.sources.subscribeSafe(self) return self.group def onNext(self, value): with self.gate: if self.activeCount < self.parent.maxConcurrency: self.activeCount += 1 self.subscribe(value) else: self.q.put_nowait(value) def onError(self, exception): with self.gate: self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.isStopped = True if self.activeCount == 0: self.observer.onCompleted() self.dispose() else: self.sourceSubscription.dispose() def subscribe(self, innerSource): subscription = SingleAssignmentDisposable() self.group.add(subscription) subscription.disposable = innerSource.subscribeSafe(self.LockObserver(self, subscription)) class LockObserver(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def onNext(self, value): with self.parent.gate: self.parent.observer.onNext(value) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): self.parent.group.remove(self.subscription) with self.parent.gate: if self.parent.q.qsize() > 0: s = self.q.get() self.parent.subscribe(s) else: self.parent.activeCount -= 1 if self.parent.isStopped and self.parent.activeCount == 0: self.parent.observer.onCompleted() self.parent.dispose()
class SerialSink(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Merge.SerialSink, self).__init__(observer, cancel) self.parent = parent def run(self): self.gate = RLock() self.isStopped = False self.group = CompositeDisposable() self.sourceSubscription = SingleAssignmentDisposable() self.group.add(self.sourceSubscription) self.sourceSubscription.disposable = self.parent.sources.subscribeSafe(self) return self.group def onNext(self, value): innerSubscription = SingleAssignmentDisposable() self.group.add(innerSubscription) innerSubscription.disposable = value.subscribeSafe(self.LockObserver(self, innerSubscription)) def onError(self, exception): with self.gate: self.observer.onError(exception) self.dispose() def onCompleted(self): self.isStopped = True if self.group.length == 1: # # Notice there can be a race between OnCompleted of the source and any # of the inner sequences, where both see _group.Count == 1, and one is # waiting for the lock. There won't be a double OnCompleted observation # though, because the call to Dispose silences the observer by swapping # in a NopObserver<T>. # with self.gate: self.observer.onCompleted() self.dispose() else: self.sourceSubscription.dispose() class LockObserver(Observer): def __init__(self, parent, subscription): self.parent = parent self.subscription = subscription def onNext(self, value): with self.parent.gate: self.parent.observer.onNext(value) def onError(self, exception): with self.parent.gate: self.parent.observer.onError(exception) self.parent.dispose() def onCompleted(self): self.parent.group.remove(self.subscription) if self.parent.isStopped and self.parent.group.length == 1: # # Notice there can be a race between OnCompleted of the source and any # of the inner sequences, where both see _group.Count == 1, and one is # waiting for the lock. There won't be a double OnCompleted observation # though, because the call to Dispose silences the observer by swapping # in a NopObserver<T>. # with self.parent.gate: self.parent.observer.onCompleted() self.parent.dispose()