HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_ThreadQueue.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_ThreadQueue.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  * Modelled after Python's Queue, this is a simple queue
10  * which you can use to communicate to another thread with.
11  */
12 
13 #ifndef __UT_ThreadQueue__
14 #define __UT_ThreadQueue__
15 
16 #include "UT_API.h"
17 #include "UT_Condition.h"
18 #include "UT_NonCopyable.h"
19 #include "UT_RingBuffer.h"
20 #include "UT_Thread.h"
21 #include <utility>
22 
23 ///
24 /// UT_ThreadQueue
25 ///
26 /// Designed to be templated on a POD.
27 ///
28 template <typename T>
30 {
31 public:
32  /// A max cost of -1 will never block on adding items to the queue.
33  UT_ThreadQueue(exint maxcost = -1)
34  {
35  myMaxCost = maxcost;
36  myCurrentCost = 0;
37  }
39 
40  /// Prohibit copying as I am not sure if lock semantics will work.
42 
43  /// Synchronized test for number of entries
44  int entries() const
45  {
46  UT_AutoLock l(myLock);
47 
48  return myList.entries();
49  }
50 
51  /// Removes an item, returns false if failed to remove because
52  /// the queue was empty.
53  bool remove(T &item)
54  {
55  UT_AutoLock l(myLock);
56 
57  if (isEmpty())
58  return false;
59  item = std::move(myList.popFirst());
60  exint cost = myCost.popFirst();
61  myCurrentCost -= cost;
62 
63  // Let people know it may now be empty.
64  myCond.triggerAll();
65  return true;
66  }
67 
68  /// Blocks until the item is ready.
70  {
71  UT_AutoLock l(myLock);
72  T result;
73 
74  while (!remove(result))
75  {
76  myCond.waitForTrigger(myLock);
77  }
78  return result;
79  }
80 
81  /// Blocks until the queue is empty.
82  /// May not still be empty, since someone could add after
83  /// you reach empty!
84  void waitForEmpty()
85  {
86  UT_AutoLock l(myLock);
87 
88  while (!isEmpty())
89  {
90  myCond.waitForTrigger(myLock);
91  }
92  }
93 
94  /// Blocks until a queue change occurs, returns the new queue size.
95  /// Returns zero immediately if queue is empty.
97  {
98  UT_AutoLock l(myLock);
99 
100  if (isEmpty())
101  return 0;
102 
103  myCond.waitForTrigger(myLock);
104  return myList.entries();
105  }
106 
107  /// Adds the item to the queue.
108  /// Will block if it the total cost would be exceeded by
109  /// adding this to the queue.
110  /// Zero cost never block, nor does a max cost of -1
111  /// @{
112  void append(const T &item, exint cost = 0)
113  { appendImpl(item, cost); }
114  void append(T &&item, exint cost = 0)
115  { appendImpl(std::move(item), cost); }
116  /// @}
117 
118 private:
119  /// Non-synchronized, do not call outside of the lock.
120  bool isEmpty() const
121  {
122  return !myList.entries();
123  }
124 
125  template <typename S>
126  void appendImpl(S &&item, exint cost)
127  {
128  UT_AutoLock l(myLock);
129 
130  // Check if we'll exceed the cost.
131  while (1)
132  {
133  // IF we are empty, add even if too expensive!
134  if (cost && myMaxCost >= 0 && (myCurrentCost > 0) && (myCurrentCost + cost > myMaxCost))
135  {
136  // Too expensive to add right now, so await a trigger.
137  myCond.waitForTrigger(myLock);
138  }
139  else
140  {
141  // Enough room for the new item.
142  break;
143  }
144  }
145 
146  // Append
147  myList.push(std::forward<S>(item));
148  myCost.push(cost);
149  myCurrentCost += cost;
150 
151  // Alert anyone waiting to wake up.
152  myCond.triggerAll();
153  }
154 
155 private:
156  UT_RingBuffer<T> myList;
157  UT_RingBuffer<exint> myCost;
158  exint myMaxCost;
159  exint myCurrentCost;
160 
161  mutable UT_Lock myLock;
162  UT_Condition myCond;
163 };
164 
165 #endif
166 
167 
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
SYS_NO_DISCARD_RESULT T popFirst()
Definition: UT_RingBuffer.h:53
int64 exint
Definition: SYS_Types.h:125
**But if you need a result
Definition: thread.h:613
Condition synchronization primitive.
Definition: UT_Condition.h:25
int waitForQueueChange()
UT_ThreadQueue(exint maxcost=-1)
A max cost of -1 will never block on adding items to the queue.
void waitForTrigger(UT_Lock &lock)
void append(const T &item, exint cost=0)
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
void triggerAll()
int push(const T &data)
Definition: UT_RingBuffer.h:63
void append(T &&item, exint cost=0)
T waitAndRemove()
Blocks until the item is ready.
int entries() const
Prohibit copying as I am not sure if lock semantics will work.