void Signal(PublisherSwitchMapSubscriber sender, R value, bool done) { if (Volatile.Read(ref index) != sender.Index()) { if (done) { Exception e = sender.Error(); if (e != null) { RxAdvancedFlowPlugins.OnError(e); } } return; } PublisherSwitchMapStruct s = new PublisherSwitchMapStruct(); s.sender = sender; s.value = value; s.done = done; lock (this) { q.OfferRef(ref s); } if (done) { sender.SetDone(); } Drain(); }
public void Cancel() { s.Cancel(); bp.Cancel(); PublisherSwitchMapSubscriber i = Volatile.Read(ref inner); if (i != Cancelled) { i = Interlocked.Exchange(ref inner, Cancelled); if (i != Cancelled) { i?.Cancel(); } } }
public void OnNext(T t) { long idx = Interlocked.Increment(ref index); PublisherSwitchMapSubscriber curr = inner; if (curr == Cancelled) { return; } inner?.Cancel(); IPublisher <R> p; try { p = mapper(t); } catch (Exception ex) { OnError(ex); return; } if (p == null) { OnError(new NullReferenceException("The mapper returned a null IPublisher")); return; } PublisherSwitchMapSubscriber i = new PublisherSwitchMapSubscriber(idx, this, bp.Requested()); if (Interlocked.CompareExchange(ref inner, i, curr) == curr) { p.Subscribe(i); } }
void Drain() { if (!bp.Enter()) { return; } ISubscriber <R> a = actual; int missed = 1; for (;;) { long r = bp.Requested(); long e = 0L; for (;;) { PublisherSwitchMapStruct v; bool empty = q.Peek(out v); if (CheckTerminated(Volatile.Read(ref done), empty, a)) { return; } if (empty) { if (e != 0L) { bp.Produced(e); } break; } PublisherSwitchMapSubscriber sender = v.sender; if (Volatile.Read(ref index) == sender.Index()) { if (v.done) { Exception ex = sender.Error(); if (ex != null) { Cancel(); q.Clear(); a.OnError(ex); return; } q.Drop(); } else if (r != e) { a.OnNext(v.value); q.Drop(); e++; } else { if (e != 0L) { bp.Produced(e); sender.Request(e); } break; } } else { q.Drop(); } } if (CheckTerminated(Volatile.Read(ref done), q.IsEmpty(), a)) { return; } if (e != 0L) { bp.Produced(e); } missed = bp.Leave(missed); if (missed == 0) { break; } } }