You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Async/AsyncManualResetEvent.cs

160 lines
5.0 KiB

6 years ago
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ZeroLevel.Services.Async
{
/// <summary>
/// An async-compatible manual-reset event.
/// </summary>
[DebuggerDisplay("Id = {Id}, IsSet = {GetStateForDebugger}")]
[DebuggerTypeProxy(typeof(DebugView))]
public sealed class AsyncManualResetEvent
{
/// <summary>
/// The object used for synchronization.
/// </summary>
private readonly object _mutex;
/// <summary>
/// The current state of the event.
/// </summary>
private TaskCompletionSource<object> _tcs;
/// <summary>
/// The semi-unique identifier for this instance. This is 0 if the id has not yet been created.
/// </summary>
private int _id;
[DebuggerNonUserCode]
private bool GetStateForDebugger
{
get
{
return _tcs.Task.IsCompleted;
}
}
/// <summary>
/// Creates an async-compatible manual-reset event.
/// </summary>
/// <param name="set">Whether the manual-reset event is initially set or unset.</param>
public AsyncManualResetEvent(bool set)
{
_mutex = new object();
_tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource<object>();
if (set)
_tcs.TrySetResult(null);
}
/// <summary>
/// Creates an async-compatible manual-reset event that is initially unset.
/// </summary>
public AsyncManualResetEvent()
: this(false)
{
}
/// <summary>
/// Gets a semi-unique identifier for this asynchronous manual-reset event.
/// </summary>
public int Id
{
get { return IdManager<AsyncManualResetEvent>.GetId(ref _id); }
}
/// <summary>
/// Whether this event is currently set. This member is seldom used; code using this member has a high possibility of race conditions.
/// </summary>
public bool IsSet
{
get { lock (_mutex) return _tcs.Task.IsCompleted; }
}
/// <summary>
/// Asynchronously waits for this event to be set.
/// </summary>
public Task WaitAsync()
{
lock (_mutex)
{
return _tcs.Task;
}
}
/// <summary>
/// Asynchronously waits for this event to be set or for the wait to be canceled.
/// </summary>
/// <param name="cancellationToken">The cancellation token used to cancel the wait. If this token is already canceled, this method will first check whether the event is set.</param>
public Task WaitAsync(CancellationToken cancellationToken)
{
var waitTask = WaitAsync();
if (waitTask.IsCompleted)
return waitTask;
return waitTask.WaitAsync(cancellationToken);
}
/// <summary>
/// Synchronously waits for this event to be set. This method may block the calling thread.
/// </summary>
public void Wait()
{
WaitAsync().WaitAndUnwrapException();
}
/// <summary>
/// Synchronously waits for this event to be set. This method may block the calling thread.
/// </summary>
/// <param name="cancellationToken">The cancellation token used to cancel the wait. If this token is already canceled, this method will first check whether the event is set.</param>
public void Wait(CancellationToken cancellationToken)
{
var ret = WaitAsync();
if (ret.IsCompleted)
return;
ret.WaitAndUnwrapException(cancellationToken);
}
/// <summary>
/// Sets the event, atomically completing every task returned by <see cref="O:Nito.AsyncEx.AsyncManualResetEvent.WaitAsync"/>. If the event is already set, this method does nothing.
/// </summary>
public void Set()
{
lock (_mutex)
{
_tcs.TrySetResult(null);
}
}
/// <summary>
/// Resets the event. If the event is already reset, this method does nothing.
/// </summary>
public void Reset()
{
lock (_mutex)
{
if (_tcs.Task.IsCompleted)
_tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource<object>();
}
}
// ReSharper disable UnusedMember.Local
[DebuggerNonUserCode]
private sealed class DebugView
{
private readonly AsyncManualResetEvent _mre;
public DebugView(AsyncManualResetEvent mre)
{
_mre = mre;
}
public int Id { get { return _mre.Id; } }
public bool IsSet { get { return _mre.GetStateForDebugger; } }
public Task CurrentTask { get { return _mre._tcs.Task; } }
}
6 years ago
// ReSharper restore UnusedMember.Local
}
}

Powered by TurnKey Linux.