CatchScheduler<TException>
using System.Reactive.Disposables;
using System.Runtime.CompilerServices;
namespace System.Reactive.Concurrency
{
    [System.Runtime.CompilerServices.NullableContext(1)]
    [System.Runtime.CompilerServices.Nullable(0)]
    internal sealed class CatchScheduler<[System.Runtime.CompilerServices.Nullable(0)] TException> : SchedulerWrapper where TException : Exception
    {
        [System.Runtime.CompilerServices.Nullable(0)]
        private class CatchSchedulerLongRunning : ISchedulerLongRunning
        {
            private readonly ISchedulerLongRunning _scheduler;
            private readonly Func<TException, bool> _handler;
            public CatchSchedulerLongRunning(ISchedulerLongRunning scheduler, Func<TException, bool> handler)
            {
                _scheduler = scheduler;
                _handler = handler;
            }
            public IDisposable ScheduleLongRunning<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, Action<TState, ICancelable> action)
            {
                return this._scheduler.ScheduleLongRunning<TState>(state, (Action<TState, ICancelable>)delegate(TState state1, ICancelable cancel) {
                    try {
                        action(state1, cancel);
                    } catch (TException val) when () {
                    }
                });
            }
        }
        [System.Runtime.CompilerServices.Nullable(0)]
        private sealed class CatchSchedulerPeriodic : ISchedulerPeriodic
        {
            [System.Runtime.CompilerServices.Nullable(0)]
            private sealed class PeriodicallyScheduledWorkItem<[System.Runtime.CompilerServices.Nullable(2)] TState> : IDisposable
            {
                private SingleAssignmentDisposableValue _cancel;
                private bool _failed;
                private readonly Func<TState, TState> _action;
                [System.Runtime.CompilerServices.Nullable(new byte[] {
                    1,
                    0
                })]
                private readonly CatchSchedulerPeriodic _catchScheduler;
                public PeriodicallyScheduledWorkItem([System.Runtime.CompilerServices.Nullable(new byte[] {
                    1,
                    0
                })] CatchSchedulerPeriodic scheduler, TState state, TimeSpan period, Func<TState, TState> action)
                {
                    _catchScheduler = scheduler;
                    _action = action;
                    _cancel.Disposable = scheduler._scheduler.SchedulePeriodic<TState>(state, period, (Func<TState, TState>)((TState state1) => Tick(state1).state));
                }
                public void Dispose()
                {
                    _cancel.Dispose();
                }
                [return: System.Runtime.CompilerServices.Nullable(new byte[] {
                    0,
                    1,
                    0,
                    1,
                    1
                })]
                private (PeriodicallyScheduledWorkItem<TState> this, TState state) Tick(TState state)
                {
                    if (!_failed)
                        try {
                            return (this, _action(state));
                        } catch (TException val) {
                            TException arg = (TException)val;
                            _failed = true;
                            if (!_catchScheduler._handler(arg))
                                throw;
                            _cancel.Dispose();
                            return default((PeriodicallyScheduledWorkItem<TState>, TState));
                        }
                    return default((PeriodicallyScheduledWorkItem<TState>, TState));
                }
            }
            private readonly ISchedulerPeriodic _scheduler;
            private readonly Func<TException, bool> _handler;
            public CatchSchedulerPeriodic(ISchedulerPeriodic scheduler, Func<TException, bool> handler)
            {
                _scheduler = scheduler;
                _handler = handler;
            }
            public IDisposable SchedulePeriodic<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, TimeSpan period, Func<TState, TState> action)
            {
                return new PeriodicallyScheduledWorkItem<TState>(this, state, period, action);
            }
        }
        private readonly Func<TException, bool> _handler;
        public CatchScheduler(IScheduler scheduler, Func<TException, bool> handler)
            : base(scheduler)
        {
            _handler = handler;
        }
        protected override Func<IScheduler, TState, IDisposable> Wrap<[System.Runtime.CompilerServices.Nullable(2)] TState>(Func<IScheduler, TState, IDisposable> action)
        {
            return delegate(IScheduler self, TState state) {
                try {
                    return action(GetRecursiveWrapper(self), state);
                } catch (TException val) when () {
                    return Disposable.Empty;
                }
            };
        }
        public CatchScheduler(IScheduler scheduler, Func<TException, bool> handler, ConditionalWeakTable<IScheduler, IScheduler> cache)
            : base(scheduler, cache)
        {
            _handler = handler;
        }
        protected override SchedulerWrapper Clone(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)
        {
            return new CatchScheduler<TException>(scheduler, _handler, cache);
        }
        protected override bool TryGetService(IServiceProvider provider, Type serviceType, [System.Runtime.CompilerServices.Nullable(2)] out object service)
        {
            service = provider.GetService(serviceType);
            if (service != null) {
                if (serviceType == typeof(ISchedulerLongRunning))
                    service = new CatchSchedulerLongRunning((ISchedulerLongRunning)service, _handler);
                else if (serviceType == typeof(ISchedulerPeriodic)) {
                    service = new CatchSchedulerPeriodic((ISchedulerPeriodic)service, _handler);
                }
            }
            return true;
        }
    }
}