// this code is borrowed from RxOfficial(rx.codeplex.com) and modified
using System;
using System.Collections.Generic;
namespace UniRx.InternalUtil
{
///
/// Asynchronous lock.
///
internal sealed class AsyncLock : IDisposable
{
private readonly Queue queue = new Queue();
private bool isAcquired = false;
private bool hasFaulted = false;
///
/// 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.
///
/// Action to queue for execution.
/// is null.
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;
}
}
}
}
///
/// Clears the work items in the queue and drops further work being queued.
///
public void Dispose()
{
lock (queue)
{
queue.Clear();
hasFaulted = true;
}
}
}
}