上海虹口龙之梦项目
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.

86 lines
2.4 KiB

8 months ago
// this code is borrowed from RxOfficial(rx.codeplex.com) and modified
using System;
using System.Collections.Generic;
namespace UniRx.InternalUtil
{
/// <summary>
/// Asynchronous lock.
/// </summary>
internal sealed class AsyncLock : IDisposable
{
private readonly Queue<Action> queue = new Queue<Action>();
private bool isAcquired = false;
private bool hasFaulted = false;
/// <summary>
/// Queues the action for execution. If the caller acquires the lock and becomes the owner,
/// the queue is processed. If the lock is already owned, the action is queued and will get
/// processed by the owner.
/// </summary>
/// <param name="action">Action to queue for execution.</param>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
public void Wait(Action action)
{
if (action == null)
throw new ArgumentNullException("action");
var isOwner = false;
lock (queue)
{
if (!hasFaulted)
{
queue.Enqueue(action);
isOwner = !isAcquired;
isAcquired = true;
}
}
if (isOwner)
{
while (true)
{
var work = default(Action);
lock (queue)
{
if (queue.Count > 0)
work = queue.Dequeue();
else
{
isAcquired = false;
break;
}
}
try
{
work();
}
catch
{
lock (queue)
{
queue.Clear();
hasFaulted = true;
}
throw;
}
}
}
}
/// <summary>
/// Clears the work items in the queue and drops further work being queued.
/// </summary>
public void Dispose()
{
lock (queue)
{
queue.Clear();
hasFaulted = true;
}
}
}
}