I'm wrote Asynchronous Lock provider for reducing lock that breaks async
keyword.
All tasks with async
and await
keywords are chained by GetAwaiter().OnCompleted(Callback)
on I know. But some cases are not, for example: lock
keyword, EventObject.Wait()
, Mutex like objects... etc.
So, I think that if asynchronous chainable lock is possible, it can improve async
performance.
/// <summary>
/// Asynchronous Lock Provider.
/// </summary>
public class AsyncLock
{
private Task m_Current = null;
/// <summary>
/// Wait the lock asynchronously.
/// </summary>
/// <returns></returns>
public async Task<IDisposable> WaitAsync()
{
var Current = new TaskCompletionSource<bool>();
while (true)
{
Task Latest = null;
lock (this)
{
if (m_Current is null || m_Current.IsCompleted)
{
m_Current = Current.Task;
break;
}
Latest = m_Current;
}
await Latest;
}
return new ReleaseOnDispose(() => Current.TrySetResult(true));
}
/// <summary>
/// Release on Dispose.
/// </summary>
private struct ReleaseOnDispose : IDisposable
{
private Action m_Release;
/// <summary>
/// Construct a new ReleaseAsync structure using Release functor.
/// </summary>
/// <param name="Release"></param>
public ReleaseOnDispose(Action Release)
=> m_Release = Release;
/// <summary>
/// Release the Lock on dispose.
/// </summary>
public void Dispose() => m_Release?.Invoke();
}
}
Usage:
/// <summary>
/// Read bytes with buffered.
/// </summary>
/// <param name="Length"></param>
/// <returns></returns>
public async Task<byte[]> ReadAsync(int Length)
{
using (await m_ReadLock.WaitAsync())
{
byte[] Output = m_Buffer.Take(Length);
if (Output.Length <= 0)
{
int Read = await m_Link.ReadAsync(new ArraySegment<byte>(m_ByteBuffer));
if (Read <= 0)
{
await m_Link.CloseAsync();
return null;
}
if (Read > Length)
{
m_Buffer.Append(m_ByteBuffer, Length, Read - Length);
Read = Length;
}
Array.Resize(ref Output, Read);
Array.Copy(m_ByteBuffer, 0, Output, 0, Read);
}
return Output;
}
}
- Is this really better than traditionally used locks?
- Can my code be accepted on commercial development?