public IDisposable Subscribe(IObserver <T> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } IObserver <T> original; IObserver <T> nextState; do { original = _current; if (original == FastSubjectHelpers <T> .DisposedSubjectMarker) { throw new ObjectDisposedException(""); } if (original == FastSubjectHelpers <T> .CompletedSubjectMarker) { observer.OnCompleted(); return(Disposable.Empty); } if (original is FastSubjectHelpers <T> .ExceptionedSubject) { observer.OnError(((FastSubjectHelpers <T> .ExceptionedSubject)original).Error); return(Disposable.Empty); } if (original == FastSubjectHelpers <T> .EmptySubjectMarker) { nextState = observer; } else if (original is FastSubjectHelpers <T> .MultiSubject) { var originalArray = ((FastSubjectHelpers <T> .MultiSubject)original).Array; var originalCount = originalArray.Length; var newArray = new IObserver <T> [originalCount + 1]; Array.Copy(originalArray, newArray, originalCount); newArray[originalCount] = observer; nextState = new FastSubjectHelpers <T> .MultiSubject(newArray); } else { nextState = new FastSubjectHelpers <T> .MultiSubject(new[] { original, observer }); } } while (Interlocked.CompareExchange(ref _current, nextState, original) != original); return(new FastSubjectHelpers <T> .Subscription(this, observer)); }
public void Unsubscribe(IObserver <T> observer) { IObserver <T> original; IObserver <T> nextState; do { original = _current; if (original is IStoppedSubjectMarker) { return; } if (original is FastSubjectHelpers <T> .MultiSubject) { var originalArray = ((FastSubjectHelpers <T> .MultiSubject)original).Array; var indexOf = Array.IndexOf(originalArray, observer); if (indexOf < 0) { return; } if (originalArray.Length == 2) { nextState = originalArray[1 - indexOf]; } else { var newArray = new IObserver <T> [originalArray.Length - 1]; Array.Copy(originalArray, newArray, indexOf); Array.Copy(originalArray, indexOf + 1, newArray, indexOf, newArray.Length - indexOf); nextState = new FastSubjectHelpers <T> .MultiSubject(newArray); } } else { if (original != observer) { return; } nextState = FastSubjectHelpers <T> .EmptySubjectMarker; } } while (Interlocked.CompareExchange(ref _current, nextState, original) != original); }
public void OnNext(T value) { IObserver <T> original; IObserver <T> nextState; do { original = _current; if (original is FastSubjectHelpers <T> .SingleSubjectWithValue) { nextState = new FastSubjectHelpers <T> .SingleSubjectWithValue( ((FastSubjectHelpers <T> .SingleSubjectWithValue)original).Observer, value); } else if (original is FastSubjectHelpers <T> .EmptySubjectWithValue || original == FastSubjectHelpers <T> .EmptySubjectMarker) { nextState = new FastSubjectHelpers <T> .EmptySubjectWithValue(value); } else if (original is FastSubjectHelpers <T> .MultiSubjectWithValue) { nextState = new FastSubjectHelpers <T> .MultiSubjectWithValue( ((FastSubjectHelpers <T> .MultiSubjectWithValue)original).Array, value); } else if (original is FastSubjectHelpers <T> .MultiSubject) { nextState = new FastSubjectHelpers <T> .MultiSubjectWithValue( ((FastSubjectHelpers <T> .MultiSubject)original).Array, value); } else if (original is IStoppedSubjectMarker) { break; } else { nextState = new FastSubjectHelpers <T> .SingleSubjectWithValue(original, value); } } while (Interlocked.CompareExchange(ref _current, nextState, original) != original); original.OnNext(value); }