Ejemplo n.º 1
0
 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));
         }
     }
 }
Ejemplo n.º 2
0
 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);
     }
 }
Ejemplo n.º 3
0
        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));
                }
            }
        }
Ejemplo n.º 4
0
 public Task <bool> WaitAsync(CancellationToken ct, TimeoutDuration timeout)
 => WaitAsync(ct: ct, timeout: timeout, treatCancellationAsTimeoutExpiry: false);