| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the Apache 2.0 License.
- // See the LICENSE file in the project root for more information.
- using System.Threading;
- namespace System.Reactive
- {
- internal class CheckedObserver<T> : IObserver<T>
- {
- private readonly IObserver<T> _observer;
- private int _state;
- private const int IDLE = 0;
- private const int BUSY = 1;
- private const int DONE = 2;
- public CheckedObserver(IObserver<T> observer)
- {
- _observer = observer;
- }
- public void OnNext(T value)
- {
- CheckAccess();
- try
- {
- _observer.OnNext(value);
- }
- finally
- {
- Interlocked.Exchange(ref _state, IDLE);
- }
- }
- public void OnError(Exception error)
- {
- CheckAccess();
- try
- {
- _observer.OnError(error);
- }
- finally
- {
- Interlocked.Exchange(ref _state, DONE);
- }
- }
- public void OnCompleted()
- {
- CheckAccess();
- try
- {
- _observer.OnCompleted();
- }
- finally
- {
- Interlocked.Exchange(ref _state, DONE);
- }
- }
- private void CheckAccess()
- {
- switch (Interlocked.CompareExchange(ref _state, BUSY, IDLE))
- {
- case BUSY:
- throw new InvalidOperationException(Strings_Core.REENTRANCY_DETECTED);
- case DONE:
- throw new InvalidOperationException(Strings_Core.OBSERVER_TERMINATED);
- }
- }
- }
- }
|