public WrapperStreamObserver(IStreamObserver <TK, TP> o, OwnedThreadsScheduler scheduler, Guid classId, TaskEntry t) { this.o = o; this.scheduler = scheduler; this.classId = classId; this.te = t; }
public IStreamObserver <TK, TP> RegisterStreamObserver <TK, TP>(IStreamObserver <TK, TP> o, Guid?classId = null) { // Check if already wrapped if (o as WrapperStreamObserver <TK, TP> != null) { return(o); } var cid = o.ClassId; if (this.useCommonSprayPool && (classId != null)) { cid = classId.Value; } var t = new TaskEntry(cid, m => o.OnNext((StreamMessage <TK, TP>)m), o.OnCompleted, o.OnFlush, o.OnError); this.taskTable.TryAdd(cid, t); return(new WrapperStreamObserver <TK, TP>(o, this, t)); }
public void Run(object obj) { int id = (int)obj; if (this.scheduler.affinitize) { NativeMethods.AffinitizeThread(id); } TaskEntry te = null; while (!this.stopped) { lock (this.scheduler.global) { if (te != null) { if (te.TaskCount > 0) { // Add operator back to pending list with corrected priority te.Status = TaskEntryStatus.HasWork; this.scheduler.pendingTasks.Add(te); } else { te.Status = TaskEntryStatus.Inactive; } } te = null; while (!this.stopped && (this.scheduler.pendingTasks.Count == 0)) { Monitor.Wait(this.scheduler.global); } if (this.stopped) { return; } this.scheduler.pendingTasks.TryGetFirst(out te); this.scheduler.pendingTasks.Remove(te); te.Status = TaskEntryStatus.Processing; if (this.scheduler.pendingTasks.Count > 0) { Monitor.Pulse(this.scheduler.global); } } try { long now = -1; long mt = -1; int par = 0; while (te.tasks.TryPeek(out var message)) { mt = message.Kind == MessageKind.DataBatch ? message.Message.MinTimestamp : StreamEvent.InfinitySyncTime; if ((now == -1) || (now == mt)) { now = mt; if (!te.tasks.TryDequeue(out message)) { throw new InvalidOperationException("Could not dequeue task from task entry"); } var newCount = Interlocked.Decrement(ref te.TaskCount); switch (message.Kind) { case MessageKind.DataBatch: if (te.Disposed) { message.Message.Free(); } else { te.onNext(message.Message); } break; case MessageKind.Completed: if (!te.Completed) { te.OnCompleted(); this.scheduler.taskTable.TryRemove(te.ClassId, out var tmp); } break; case MessageKind.Flush: te.onFlush(); break; } par++; if (newCount == 0) { break; } } else { te.Priority = mt; if (this.scheduler.pendingTasks.Count > 0) { break; } now = mt; } } } catch (Exception e) { te.onError(e); } } }