ThreadControlQueue.cs 2.5 KB

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