ThreadControlQueue.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. namespace PF {
  2. /** Queue of paths to be processed by the system */
  3. class ThreadControlQueue
  4. {
  5. Path head;
  6. Path tail;
  7. /** Create a new queue with the specified number of receivers.
  8. * It is important that the number of receivers is fixed.
  9. * Properties like AllReceiversBlocked rely on knowing the exact number of receivers using the Pop (or PopNoBlock) methods.
  10. */
  11. public ThreadControlQueue (int numReceivers) {
  12. }
  13. /** True if the queue is empty */
  14. public bool IsEmpty {
  15. get {
  16. return head == null;
  17. }
  18. }
  19. /** Push a path to the front of the queue */
  20. public void PushFront (Path path) {
  21. if (tail == null) {// (tail == null) ==> (head == null)
  22. head = path;
  23. tail = path;
  24. } else {
  25. path.next = head;
  26. head = path;
  27. }
  28. }
  29. /** Push a path to the end of the queue */
  30. public void Push (Path path) {
  31. if (tail == null) {// (tail == null) ==> (head == null)
  32. head = path;
  33. tail = path;
  34. } else {
  35. tail.next = path;
  36. tail = path;
  37. }
  38. }
  39. /** Pops the next item off the queue.
  40. * This call will block if there are no items in the queue or if the queue is currently blocked.
  41. *
  42. * \returns A Path object, guaranteed to be not null.
  43. * \throws QueueTerminationException if #TerminateReceivers has been called.
  44. * \throws System.InvalidOperationException if more receivers get blocked than the fixed count sent to the constructor
  45. */
  46. public Path Pop ()
  47. {
  48. if (this.head == null)
  49. {
  50. return null;
  51. }
  52. Path p = head;
  53. var newHead = head.next;
  54. if (newHead == null)
  55. {
  56. tail = null;
  57. }
  58. head.next = null;
  59. head = newHead;
  60. return p;
  61. }
  62. /** Pops the next item off the queue, this call will not block.
  63. * To ensure stability, the caller must follow this pattern.
  64. * 1. Call PopNoBlock(false), if a null value is returned, wait for a bit (e.g yield return null in a Unity coroutine)
  65. * 2. try again with PopNoBlock(true), if still null, wait for a bit
  66. * 3. Repeat from step 2.
  67. *
  68. * \throws QueueTerminationException if #TerminateReceivers has been called.
  69. * \throws System.InvalidOperationException if more receivers get blocked than the fixed count sent to the constructor
  70. */
  71. public Path PopNoBlock (bool blockedBefore)
  72. {
  73. if (this.head == null)
  74. {
  75. return null;
  76. }
  77. Path p = head;
  78. var newHead = head.next;
  79. if (newHead == null) {
  80. tail = null;
  81. }
  82. head.next = null;
  83. head = newHead;
  84. return p;
  85. }
  86. }
  87. }