class SinkWithTimeSpan(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Window.SinkWithTimeSpan, self).__init__(observer, cancel) self.parent = parent 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 tick(self): with self.gate: self.subject.onCompleted() self.createWindow() def createWindow(self): self.subject = Subject() self.observer.onNext(AddRef(self.subject, self.refCountDisposable)) def onNext(self, value): with self.gate: self.list.append(value) def onError(self, exception): with self.gate: self.subject.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.subject.onCompleted() self.observer.onCompleted() self.dispose()
class SinkWithTimeSpan(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Window.SinkWithTimeSpan, self).__init__(observer, cancel) self.parent = parent 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 tick(self): with self.gate: self.subject.onCompleted() self.createWindow() def createWindow(self): self.subject = Subject() self.observer.onNext(AddRef(self.subject, self.refCountDisposable)) def onNext(self, value): with self.gate: self.list.append(value) def onError(self, exception): with self.gate: self.subject.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.subject.onCompleted() self.observer.onCompleted() self.dispose()
class Session(object): def __init__(self, parent): self.parent = parent self.removeHandler = None self.subject = Subject() self.count = 0 def connect(self, observer): # # We connect the given observer to the subject first, before performing any kind # of initialization which will register an event handler. This is done to ensure # we don't have a time gap between adding the handler and connecting the user's # subject, e.g. when the ImmediateScheduler is used. # # [OK] Use of unsafe Subscribe: called on a known subject implementation. # connection = self.subject.subscribe(observer) self.count += 1 if self.count == 1: try: self.initialize() except Exception as e: self.count -= 1 connection.dispose() observer.onError(e) return Disposable.empty() def dispose(): connection.dispose() with self.parent.gate: self.count -=1 if self.count == 0: self.parent.scheduler.schedule(self.removeHandler.dispose) self.parent.session = None return Disposable.create(dispose) def initialize(self): # # When the ref count goes to zero, no-one should be able to perform operations on # the session object anymore, because it gets nulled out. # assert self.removeHandler == None self.removeHandler = SingleAssignmentDisposable() # # Conversion code is supposed to be a pure function and shouldn't be run on the # scheduler, but the add handler call should. Notice the scheduler can be the # ImmediateScheduler, causing synchronous invocation. This is the default when # no SynchronizationContext is found (see QueryLanguage.Events.cs and search for # the GetSchedulerForCurrentContext method). # onNext = self.parent.getHandler(self.subject.onNext) self.parent.scheduler.scheduleWithState(onNext, self.addHandler) def addHandler(self, scheduler, onNext): try: removeHandler = self.parent.addHandler(onNext) except Exception as e: self.subject.onError(e) else: self.removeHandler.disposable = removeHandler # # We don't propagate the exception to the OnError channel upon Dispose. This is # not possible at this stage, because we've already auto-detached in the base # class Producer implementation. Even if we would switch the OnError and auto- # detach calls, it wouldn't work because the remove handler logic is scheduled # on the given scheduler, causing asynchrony. We can't block waiting for the # remove handler to run on the scheduler. # return Disposable.empty()
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 SinkWithCountAndTimeSpan(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Window.SinkWithCountAndTimeSpan, self).__init__(observer, cancel) self.parent = parent 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 createTimer(self, wId): m = SingleAssignmentDisposable() self.timerDisposable.disposable = m m.disposable = self.parent.scheduler.scheduleWithRelativeAndState( wId, self.parent.timeSpan, self.tick ) def tick(self, scheduler, wId): d = Disposable.empty() newId = 0 with self.gate: if wId != self.windowId: return d self.n = 0 self.windowId += 1 newId = self.windowId self.s.onCompleted() self.s = Subject() self.observer.onNext(AddRef(self.s, self.refCountDisposable)) self.createTimer(newId) return d def onNext(self, value): newWindow = False newId = 0 with self.gate: self.s.onNext(value) self.n += 1 if self.n == self.parent.count: newWindow = True self.n = 0 self.windowId += 1 newId = self.windowId self.s.onCompleted() self.s = Subject() self.observer.onNext(AddRef(self.s, self.refCountDisposable)) if newWindow: self.createTimer(newId) def onError(self, exception): with self.gate: self.s.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.s.onCompleted() self.observer.onCompleted() self.dispose()
class SinkWithCountAndTimeSpan(rx.linq.sink.Sink): def __init__(self, parent, observer, cancel): super(Window.SinkWithCountAndTimeSpan, self).__init__(observer, cancel) self.parent = parent 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 createTimer(self, wId): m = SingleAssignmentDisposable() self.timerDisposable.disposable = m m.disposable = self.parent.scheduler.scheduleWithRelativeAndState( wId, self.parent.timeSpan, self.tick) def tick(self, scheduler, wId): d = Disposable.empty() newId = 0 with self.gate: if wId != self.windowId: return d self.n = 0 self.windowId += 1 newId = self.windowId self.s.onCompleted() self.s = Subject() self.observer.onNext(AddRef(self.s, self.refCountDisposable)) self.createTimer(newId) return d def onNext(self, value): newWindow = False newId = 0 with self.gate: self.s.onNext(value) self.n += 1 if self.n == self.parent.count: newWindow = True self.n = 0 self.windowId += 1 newId = self.windowId self.s.onCompleted() self.s = Subject() self.observer.onNext( AddRef(self.s, self.refCountDisposable)) if newWindow: self.createTimer(newId) def onError(self, exception): with self.gate: self.s.onError(exception) self.observer.onError(exception) self.dispose() def onCompleted(self): with self.gate: self.s.onCompleted() self.observer.onCompleted() self.dispose()
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()