// 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; } } } }