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;
}
}
}