mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 17:03:10 +00:00
690f2a63e5
commit 90f285d7f6bcd926ce9ca3d5832b1d70a5eae6ab Author: JKorf <jankorf91@gmail.com> Date: Sun Jun 25 19:51:12 2023 +0200 Docs commit 72187035c703d1402b37bd2f4c3e066706f28d67 Author: JKorf <jankorf91@gmail.com> Date: Sat Jun 24 16:02:53 2023 +0200 docs commit 8411977292f1fb0b6e0705b1ad675b79a5311d90 Author: JKorf <jankorf91@gmail.com> Date: Fri Jun 23 18:25:15 2023 +0200 wip commit cb7d33aad5d2751104c8b8a6c6eadbf0d36b672c Author: JKorf <jankorf91@gmail.com> Date: Fri Jun 2 19:26:26 2023 +0200 wip commit 4359a2d05ea1141cff516dab18f364a6ca854e18 Author: JKorf <jankorf91@gmail.com> Date: Wed May 31 20:51:36 2023 +0200 wip commit c6adb1b2f728d143f6bd667139c619581122a3c9 Author: JKorf <jankorf91@gmail.com> Date: Mon May 1 21:13:47 2023 +0200 wip commit 7fee733f82fa6ff574030452f0955c9e817647dd Author: JKorf <jankorf91@gmail.com> Date: Thu Apr 27 13:02:56 2023 +0200 wip commit f8057313ffc9b0c31effcda71d35d105ea390971 Author: JKorf <jankorf91@gmail.com> Date: Mon Apr 17 21:37:51 2023 +0200 wip
109 lines
3.5 KiB
C#
109 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CryptoExchange.Net.Objects
|
|
{
|
|
/// <summary>
|
|
/// Async auto reset based on Stephen Toub`s implementation
|
|
/// https://devblogs.microsoft.com/pfxteam/building-async-coordination-primitives-part-2-asyncautoresetevent/
|
|
/// </summary>
|
|
public class AsyncResetEvent : IDisposable
|
|
{
|
|
private static readonly Task<bool> _completed = Task.FromResult(true);
|
|
private Queue<TaskCompletionSource<bool>> _waits = new Queue<TaskCompletionSource<bool>>();
|
|
private bool _signaled;
|
|
private readonly bool _reset;
|
|
|
|
/// <summary>
|
|
/// New AsyncResetEvent
|
|
/// </summary>
|
|
/// <param name="initialState"></param>
|
|
/// <param name="reset"></param>
|
|
public AsyncResetEvent(bool initialState = false, bool reset = true)
|
|
{
|
|
_signaled = initialState;
|
|
_reset = reset;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wait for the AutoResetEvent to be set
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task<bool> WaitAsync(TimeSpan? timeout = null)
|
|
{
|
|
lock (_waits)
|
|
{
|
|
if (_signaled)
|
|
{
|
|
if(_reset)
|
|
_signaled = false;
|
|
return _completed;
|
|
}
|
|
else
|
|
{
|
|
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
if(timeout != null)
|
|
{
|
|
var cancellationSource = new CancellationTokenSource(timeout.Value);
|
|
var registration = cancellationSource.Token.Register(() =>
|
|
{
|
|
lock (_waits)
|
|
{
|
|
tcs.TrySetResult(false);
|
|
|
|
// Not the cleanest but it works
|
|
_waits = new Queue<TaskCompletionSource<bool>>(_waits.Where(i => i != tcs));
|
|
}
|
|
}, useSynchronizationContext: false);
|
|
}
|
|
|
|
_waits.Enqueue(tcs);
|
|
return tcs.Task;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Signal a waiter
|
|
/// </summary>
|
|
public void Set()
|
|
{
|
|
lock (_waits)
|
|
{
|
|
if (!_reset)
|
|
{
|
|
// Act as ManualResetEvent. Once set keep it signaled and signal everyone who is waiting
|
|
_signaled = true;
|
|
while (_waits.Count > 0)
|
|
{
|
|
var toRelease = _waits.Dequeue();
|
|
toRelease.TrySetResult(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Act as AutoResetEvent. When set signal 1 waiter
|
|
if (_waits.Count > 0)
|
|
{
|
|
var toRelease = _waits.Dequeue();
|
|
toRelease.TrySetResult(true);
|
|
}
|
|
else if (!_signaled)
|
|
_signaled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
_waits.Clear();
|
|
}
|
|
}
|
|
}
|