Timeout
Helps to compute timeout for asynchronous operations.
using DotNext.Diagnostics;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace DotNext.Threading
{
[StructLayout(LayoutKind.Auto)]
public readonly struct Timeout
{
private readonly Timestamp created;
private readonly TimeSpan timeout;
public static Timeout Infinite => default(Timeout);
public static Timeout Expired { get; } = new Timeout(TimeSpan.Zero);
public TimeSpan Value {
get {
if (!IsInfinite)
return timeout;
return System.Threading.Timeout.InfiniteTimeSpan;
}
}
public bool IsInfinite => created.IsEmpty;
public bool IsExpired {
get {
if (!IsInfinite)
return created.Elapsed > timeout;
return false;
}
}
public TimeSpan? RemainingTime {
get {
if (!IsInfinite) {
TimeSpan value;
if (!((value = timeout - created.Elapsed) >= TimeSpan.Zero))
return null;
return value;
}
return System.Threading.Timeout.InfiniteTimeSpan;
}
}
public Timeout(TimeSpan timeout)
{
if (timeout == System.Threading.Timeout.InfiniteTimeSpan)
this = default(Timeout);
else {
if (timeout < TimeSpan.Zero)
throw new ArgumentOutOfRangeException("timeout");
created = new Timestamp();
this.timeout = timeout;
}
}
public void ThrowIfExpired()
{
if (IsExpired)
throw new TimeoutException();
}
public void ThrowIfExpired(out TimeSpan remaining)
{
if (IsInfinite)
remaining = System.Threading.Timeout.InfiniteTimeSpan;
else if ((remaining = timeout - created.Elapsed) < TimeSpan.Zero) {
throw new TimeoutException();
}
}
public static bool operator true([In] [IsReadOnly] ref Timeout timeout)
{
return timeout.IsExpired;
}
public static bool operator false([In] [IsReadOnly] ref Timeout timeout)
{
return !timeout.IsExpired;
}
public static implicit operator TimeSpan([In] [IsReadOnly] ref Timeout timeout)
{
return timeout.Value;
}
}
}