AscynLock.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // this code is borrowed from RxOfficial(rx.codeplex.com) and modified
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace UniRx.InternalUtil
  6. {
  7. /// <summary>
  8. /// Asynchronous lock.
  9. /// </summary>
  10. internal sealed class AsyncLock : IDisposable
  11. {
  12. private readonly Queue<Action> queue = new Queue<Action>();
  13. private bool isAcquired = false;
  14. private bool hasFaulted = false;
  15. /// <summary>
  16. /// Queues the action for execution. If the caller acquires the lock and becomes the owner,
  17. /// the queue is processed. If the lock is already owned, the action is queued and will get
  18. /// processed by the owner.
  19. /// </summary>
  20. /// <param name="action">Action to queue for execution.</param>
  21. /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
  22. public void Wait(Action action)
  23. {
  24. if (action == null)
  25. throw new ArgumentNullException("action");
  26. var isOwner = false;
  27. lock (queue)
  28. {
  29. if (!hasFaulted)
  30. {
  31. queue.Enqueue(action);
  32. isOwner = !isAcquired;
  33. isAcquired = true;
  34. }
  35. }
  36. if (isOwner)
  37. {
  38. while (true)
  39. {
  40. var work = default(Action);
  41. lock (queue)
  42. {
  43. if (queue.Count > 0)
  44. work = queue.Dequeue();
  45. else
  46. {
  47. isAcquired = false;
  48. break;
  49. }
  50. }
  51. try
  52. {
  53. work();
  54. }
  55. catch
  56. {
  57. lock (queue)
  58. {
  59. queue.Clear();
  60. hasFaulted = true;
  61. }
  62. Debug.LogError(new Exception("锁错误"));
  63. }
  64. }
  65. }
  66. }
  67. /// <summary>
  68. /// Clears the work items in the queue and drops further work being queued.
  69. /// </summary>
  70. public void Dispose()
  71. {
  72. lock (queue)
  73. {
  74. queue.Clear();
  75. hasFaulted = true;
  76. }
  77. }
  78. }
  79. }