public static TimeoutDuration SubtractElapsed(this TimeoutDuration timeout, Stopwatch stopwatch) { timeout.EnsureNotNull(nameof(timeout)); stopwatch.EnsureNotNull(nameof(stopwatch)); // if (timeout.IsInfinite) { return(timeout); } else { var elapsedMilliseconds = (int)Math.Min(int.MaxValue, stopwatch.ElapsedMilliseconds); if (elapsedMilliseconds >= timeout.Milliseconds) { return(TimeoutDuration.Zero); } else { return(new TimeoutDuration(milliseconds: timeout.Milliseconds - elapsedMilliseconds)); } } }
public static TimeoutDuration Max(this TimeoutDuration a, TimeoutDuration b) { a.EnsureNotNull(nameof(a)); b.EnsureNotNull(nameof(b)); // if (a.IsInfinite) { return(a); } else if (b.IsInfinite) { return(b); } else if (a.Milliseconds > b.Milliseconds) { return(a); } else { return(b); } }
public Task <bool> WaitAsync(CancellationToken ct, TimeoutDuration timeout, bool treatCancellationAsTimeoutExpiry) { SignalAwaitable signalAwaitable = null; try { timeout.EnsureNotNull(nameof(timeout)); // if (ct.IsCancellationRequested) { return(treatCancellationAsTimeoutExpiry ? TaskUtilities.FromFalse() : TaskUtilities.FromCanceled <bool>(ct: ct)); } else { var timeoutCts = default(CancellationTokenSource); var timeoutCtRegistration = default(CancellationTokenRegistration?); try { signalAwaitable = new SignalAwaitable(); // if (ct.CanBeCanceled) { var ctRegistration = default(CancellationTokenRegistration); try { signalAwaitable .Task .ContinueWith( continuationAction: (locTask) => { ctRegistration.Dispose(); }, continuationOptions: TaskContinuationOptions.ExecuteSynchronously); ctRegistration = ct .Register( callback: () => { if (treatCancellationAsTimeoutExpiry) { signalAwaitable.TrySetResult(result: false); } else { signalAwaitable.TrySetCanceled(ct: ct); } }); } catch { ctRegistration.Dispose(); throw; } } // if (!timeout.IsInfinite) { timeoutCts = new CancellationTokenSource(millisecondsDelay: timeout.Milliseconds); timeoutCtRegistration = timeoutCts .Token .Register(callback: () => signalAwaitable.TrySetResult(result: false)); } // var queue = ReadDA(ref _queue); var queueSpinLock = ReadDA(ref _queueSpinLock, considerDisposeRequest: true); queueSpinLock .Invoke( action: () => { if (ct.IsCancellationRequested) { if (treatCancellationAsTimeoutExpiry) { signalAwaitable.TrySetResult(result: false); } else { signalAwaitable.TrySetCanceled(ct: ct); } } else { EnsureNotDisposeState(considerDisposeRequest: true); // if (queue.Count == 1 && ReferenceEquals(queue.Peek(), __Signaled)) { if (signalAwaitable.TrySetResult(result: true)) { queue.Dequeue(); } } else if (timeout.Milliseconds == 0) { signalAwaitable.TrySetResult(result: false); } else { queue.Enqueue(signalAwaitable); } } }); return(signalAwaitable.Task); } catch { timeoutCtRegistration?.Dispose(); timeoutCts?.Dispose(); throw; } } } catch (Exception exception) { if (signalAwaitable?.TrySetException(exception) == true) { return(signalAwaitable.Task); } else { return(TaskUtilities.FromError <bool>(error: exception)); } } }