ctkEALinkedQueue_p.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #ifndef CTKEALINKEDQUEUE_P_H
  16. #define CTKEALINKEDQUEUE_P_H
  17. #include "ctkEAChannel_p.h"
  18. #include <dispatch/ctkEAInterruptibleThread_p.h>
  19. #include <QMutex>
  20. #include <QWaitCondition>
  21. /** A standard linked list node used in various queue classes **/
  22. struct ctkEALinkedNode
  23. {
  24. ctkEARunnable* value;
  25. ctkEALinkedNode* next;
  26. ctkEALinkedNode(ctkEARunnable* x = 0)
  27. : value(x), next(0)
  28. { if (x && x->autoDelete()) ++x->ref; }
  29. ctkEALinkedNode(ctkEARunnable* x, ctkEALinkedNode* n)
  30. : value(x), next(n)
  31. { if (x && x->autoDelete()) ++x->ref; }
  32. ~ctkEALinkedNode()
  33. {
  34. if (value && value->autoDelete())
  35. {
  36. if (!--value->ref) delete value;
  37. }
  38. }
  39. };
  40. /**
  41. * A linked list based channel implementation.
  42. * The algorithm avoids contention between puts
  43. * and takes when the queue is not empty.
  44. * Normally a put and a take can proceed simultaneously.
  45. * (Although it does not allow multiple concurrent puts or takes.)
  46. * This class tends to perform more efficently than
  47. * other ctkEAChannel implementations in producer/consumer
  48. * applications.
  49. */
  50. class ctkEALinkedQueue : public ctkEAChannel
  51. {
  52. protected:
  53. /**
  54. * Dummy header node of list. The first actual node, if it exists, is always
  55. * at head_->next. After each take, the old first node becomes the head.
  56. **/
  57. ctkEALinkedNode* head_;
  58. mutable QMutex headLock_;
  59. QMutex mutex_;
  60. /**
  61. * Helper monitor for managing access to last node.
  62. **/
  63. QMutex putLock_;
  64. QWaitCondition putLockWait_;
  65. /**
  66. * The last node of list. put() appends to list, so modifies last_
  67. **/
  68. ctkEALinkedNode* last_;
  69. QMutex lastLock_;
  70. /**
  71. * The number of threads waiting for a take.
  72. * Notifications are provided in put only if greater than zero.
  73. * The bookkeeping is worth it here since in reasonably balanced
  74. * usages, the notifications will hardly ever be necessary, so
  75. * the call overhead to notify can be eliminated.
  76. **/
  77. int waitingForTake_;
  78. public:
  79. ctkEALinkedQueue();
  80. ~ctkEALinkedQueue();
  81. void put(ctkEARunnable* x);
  82. bool offer(ctkEARunnable* x, long msecs);
  83. ctkEARunnable* take();
  84. ctkEARunnable* peek() const;
  85. bool isEmpty() const;
  86. ctkEARunnable* poll(long msecs);
  87. protected:
  88. /** Main mechanics for put/offer **/
  89. void insert(ctkEARunnable* x);
  90. /** Main mechanics for take/poll **/
  91. ctkEARunnable* extract();
  92. };
  93. #endif // CTKEALINKEDQUEUE_P_H