You.i Engine
YiConcurrentQueue.h
Go to the documentation of this file.
1 // © You i Labs Inc. 2000-2020. All rights reserved.
2 #ifndef _YI_CONCURRENT_QUEUE_H_
3 #define _YI_CONCURRENT_QUEUE_H_
4 
5 #include <queue>
6 
7 #include <condition_variable>
8 #include <mutex>
9 
20 template<typename YI_DATA>
22 {
23 public:
29  , m_stopWaiting(false)
30  , m_EmptyCondition(YI_SYNCHRONIZATION_OBJECT_INIT_VALUE)
31  , m_AvailableCondition(YI_SYNCHRONIZATION_OBJECT_INIT_VALUE)
32  {
33  }
34 
40  , m_stopWaiting(false)
41  , m_EmptyCondition(YI_SYNCHRONIZATION_OBJECT_INIT_VALUE)
42  , m_AvailableCondition(YI_SYNCHRONIZATION_OBJECT_INIT_VALUE)
43  {
44  std::unique_lock<std::mutex> autoMutex(other.m_mutex);
45  m_queue = other.m_queue;
46  }
47 
52  {
53  std::unique_lock<std::mutex> autoLhsMutex(m_mutex);
54  std::unique_lock<std::mutex> autoRhsMutex(rhs.m_mutex);
55  m_queue = rhs.m_queue;
56  return *this;
57  }
58 
62  void Push(const YI_DATA &rData)
63  {
64  std::unique_lock<std::mutex> autoMutex(m_mutex);
65 
66  m_queue.push(rData);
67 
68  m_AvailableCondition.notify_one();
69  }
70 
74  void WaitEmpty()
75  {
76  std::unique_lock<std::mutex> autoMutex(m_mutex);
77  while (!m_queue.empty()) // protection against 'spurious wake-ups'
78  {
79  m_EmptyCondition.wait(autoMutex);
80  }
81  }
82 
86  bool Empty() const
87  {
88  std::unique_lock<std::mutex> autoMutex(m_mutex);
89  return m_queue.empty();
90  }
91 
96  bool TryPop(YI_DATA &rValue)
97  {
98  bool successfulLock = false;
99 
100  if (m_mutex.try_lock())
101  {
102  if (!m_queue.empty())
103  {
104  rValue = m_queue.front();
105  m_queue.pop();
106 
107  successfulLock = true;
108 
109  if (m_queue.empty())
110  {
111  m_EmptyCondition.notify_all();
112  }
113  }
114 
115  m_mutex.unlock();
116  }
117 
118  return successfulLock;
119  }
120 
126  bool WaitAndPop(YI_DATA &rValue)
127  {
128  bool ret = false;
129 
130  std::unique_lock<std::mutex> autoMutex(m_mutex);
131 
132  while (m_queue.empty() && !m_stopWaiting)
133  {
134  m_AvailableCondition.wait(autoMutex);
135  }
136 
137  m_stopWaiting = false;
138 
139  if (!m_queue.empty())
140  {
141  rValue = m_queue.front();
142  m_queue.pop();
143 
144  if (m_queue.empty())
145  {
146  m_EmptyCondition.notify_all();
147  }
148 
149  ret = true;
150  }
151 
152  return ret;
153  }
154 
160  void StopWaiting()
161  {
162  std::unique_lock<std::mutex> autoMutex(m_mutex);
163 
164  m_stopWaiting = true;
165  m_AvailableCondition.notify_one();
166  }
167 
168 private:
169  std::queue<YI_DATA> m_queue;
170  mutable std::mutex m_mutex;
171 
172  bool m_stopWaiting;
173  std::condition_variable m_EmptyCondition;
174  std::condition_variable m_AvailableCondition;
175 };
176 
179 #endif // _YI_CONCURRENT_QUEUE_H_
#define YI_SYNCHRONIZATION_OBJECT_INIT_VALUE
Definition: YiPredef.h:49
void StopWaiting()
Definition: YiConcurrentQueue.h:160
void WaitEmpty()
Definition: YiConcurrentQueue.h:74
void Push(const YI_DATA &rData)
Definition: YiConcurrentQueue.h:62
CYIConcurrentQueue()
Definition: YiConcurrentQueue.h:27
A simple, thread safe queue.
Definition: YiConcurrentQueue.h:21
bool TryPop(YI_DATA &rValue)
Definition: YiConcurrentQueue.h:96
bool WaitAndPop(YI_DATA &rValue)
Definition: YiConcurrentQueue.h:126
bool Empty() const
Definition: YiConcurrentQueue.h:86
CYIConcurrentQueue & operator=(const CYIConcurrentQueue< YI_DATA > &rhs)
Definition: YiConcurrentQueue.h:51
CYIConcurrentQueue(const CYIConcurrentQueue< YI_DATA > &other)
Definition: YiConcurrentQueue.h:38