/// <summary> /// Subscribe with the relaxed IFlowableSubscriber instance. /// </summary> /// <param name="subscriber">The IFlowableSubscriber instance, not null.</param> public void Subscribe(IFlowableSubscriber <T> subscriber) { var parent = new MulticastSubscription(this, subscriber, executor.Worker, bufferSize); subscriber.OnSubscribe(parent); if (Add(parent)) { if (parent.IsCancelled()) { Remove(parent); return; } } else { var ex = Volatile.Read(ref error); if (ex == ExceptionHelper.Terminated) { subscriber.OnComplete(); } else { subscriber.OnError(ex); } } }
void Remove(MulticastSubscription ms) { for (;;) { var a = Volatile.Read(ref subscribers); int n = a.Length; if (n == 0) { break; } int j = -1; for (int i = 0; i < n; i++) { if (a[i] == ms) { j = i; break; } } if (j < 0) { break; } if (n == 1) { if (Interlocked.CompareExchange(ref subscribers, Empty, a) == a) { break; } } else { var b = new MulticastSubscription[n - 1]; Array.Copy(a, 0, b, 0, j); Array.Copy(a, j + 1, b, j, n - j - 1); if (Interlocked.CompareExchange(ref subscribers, b, a) == a) { break; } } } }
bool Add(MulticastSubscription ms) { for (;;) { var a = Volatile.Read(ref subscribers); if (a == Terminated) { return(false); } int n = a.Length; var b = new MulticastSubscription[n + 1]; Array.Copy(a, 0, b, 0, n); b[n] = ms; if (Interlocked.CompareExchange(ref subscribers, b, a) == a) { return(true); } } }