You.i Engine
YiConcurrentDeque.h
Go to the documentation of this file.
1 // © You i Labs Inc. 2000-2017. All rights reserved.
2 #ifndef _YI_CONCURRENT_DEQUE_H_
3 #define _YI_CONCURRENT_DEQUE_H_
4 
5 #include <deque>
6 
7 #include "thread/YiAutoMutex.h"
8 #include "thread/YiMutex.h"
10 
21 template<typename YI_DATA>
23 {
24 public:
26  m_bStopWaiting(false)
27  {
28  }
29 
31  m_bStopWaiting(false)
32  {
33  CYIAutoMutex autoMutex(other.m_mutex);
34  m_deque = other.m_deque;
35  }
36 
38  {
39  CYIAutoMutex autoLhsMutex(m_mutex);
40  CYIAutoMutex autoRhsMutex(rhs.m_mutex);
41  m_deque = rhs.m_deque;
42  return *this;
43  }
44 
48  void PushFront(const YI_DATA &rData)
49  {
50  CYIAutoMutex autoMutex(m_mutex);
51 
52  m_deque.push_front(rData);
53 
54  m_AvailableCondition.WakeOne();
55  }
56 
60  void PushBack(const YI_DATA &rData)
61  {
62  CYIAutoMutex autoMutex(m_mutex);
63 
64  m_deque.push_back(rData);
65 
66  m_AvailableCondition.WakeOne();
67  }
68 
72  void WaitEmpty()
73  {
74  CYIAutoMutex autoMutex(m_mutex);
75  while (!m_deque.empty()) // protection against 'spurious wake-ups'
76  {
77  m_EmptyCondition.Wait(m_mutex);
78  }
79  }
80 
84  bool Empty() const
85  {
86  CYIAutoMutex autoMutex(m_mutex);
87  return m_deque.empty();
88  }
89 
94  bool TryPopFront(YI_DATA & rValue)
95  {
96  bool bSuccessfulLock = false;
97 
98  if (m_mutex.TryLock())
99  {
100  if(!m_deque.empty())
101  {
102  rValue = m_deque.front();
103  m_deque.pop_front();
104 
105  bSuccessfulLock = true;
106 
107  if (m_deque.empty())
108  {
109  m_EmptyCondition.WakeAll();
110  }
111  }
112 
113  m_mutex.Unlock();
114  }
115 
116  return bSuccessfulLock;
117  }
118 
122  bool TryPopBack(YI_DATA & rValue)
123  {
124  bool bSuccessfulLock = false;
125 
126  if (m_mutex.TryLock())
127  {
128  if(!m_deque.empty())
129  {
130  rValue = m_deque.back();
131  m_deque.pop_back();
132 
133  bSuccessfulLock = true;
134 
135  if (m_deque.empty())
136  {
137  m_EmptyCondition.WakeAll();
138  }
139  }
140 
141  m_mutex.Unlock();
142  }
143 
144  return bSuccessfulLock;
145  }
146 
152  bool WaitAndPopFront(YI_DATA &rValue)
153  {
154  bool bRet = false;
155 
156  CYIAutoMutex autoMutex(m_mutex);
157 
158  while(m_deque.empty() && !m_bStopWaiting)
159  {
160  m_AvailableCondition.Wait(m_mutex);
161  }
162 
163  m_bStopWaiting = false;
164 
165  if (!m_deque.empty())
166  {
167  rValue = m_deque.front();
168  m_deque.pop_front();
169 
170  if (m_deque.empty())
171  {
172  m_EmptyCondition.WakeAll();
173  }
174 
175  bRet = true;
176  }
177 
178  return bRet;
179  }
180 
187  bool WaitAndPopFront(YI_DATA &rValue, uint64_t uTimeoutMs)
188  {
189  bool bRet = false;
190 
191  CYIAutoMutex autoMutex(m_mutex);
192 
193  if (!m_bStopWaiting && m_deque.empty())
194  {
195  m_AvailableCondition.Wait(m_mutex, uTimeoutMs);
196  }
197 
198  m_bStopWaiting = false;
199 
200  if (!m_deque.empty())
201  {
202  rValue = m_deque.front();
203  m_deque.pop_front();
204 
205  if (m_deque.empty())
206  {
207  m_EmptyCondition.WakeAll();
208  }
209 
210  bRet = true;
211  }
212 
213  return bRet;
214  }
215 
219  bool WaitAndPopBack(YI_DATA & rValue)
220  {
221  bool bRet = false;
222 
223  CYIAutoMutex autoMutex(m_mutex);
224 
225  while(m_deque.empty() && !m_bStopWaiting)
226  {
227  m_AvailableCondition.Wait(m_mutex);
228  }
229 
230  m_bStopWaiting = false;
231 
232  if (!m_deque.empty())
233  {
234  rValue = m_deque.back();
235  m_deque.pop_back();
236 
237  if (m_deque.empty())
238  {
239  m_EmptyCondition.WakeAll();
240  }
241 
242  bRet = true;
243  }
244 
245  return bRet;
246  }
247 
254  void StopWaiting()
255  {
256  CYIAutoMutex autoMutex(m_mutex);
257 
258  m_bStopWaiting = true;
259  m_AvailableCondition.WakeOne();
260  }
261 
265  uint32_t GetSize() const
266  {
267  CYIAutoMutex autoMutex(m_mutex);
268  return (uint32_t)m_deque.size();
269  }
270 
271 private:
272  std::deque<YI_DATA> m_deque;
273  mutable CYIMutex m_mutex;
274 
275  bool m_bStopWaiting;
276  CYIWaitCondition m_EmptyCondition;
277  CYIWaitCondition m_AvailableCondition;
278 
279 };
280 
283 #endif // _YI_CONCURRENT_DEQUE_H_
void PushBack(const YI_DATA &rData)
Definition: YiConcurrentDeque.h:60
bool TryPopBack(YI_DATA &rValue)
Definition: YiConcurrentDeque.h:122
Definition: YiMutex.h:110
bool WaitAndPopFront(YI_DATA &rValue, uint64_t uTimeoutMs)
Definition: YiConcurrentDeque.h:187
bool Unlock()
CYIConcurrentDeque(const CYIConcurrentDeque< YI_DATA > &other)
Definition: YiConcurrentDeque.h:30
CYIConcurrentDeque()
Definition: YiConcurrentDeque.h:25
void StopWaiting()
Definition: YiConcurrentDeque.h:254
bool WaitAndPopFront(YI_DATA &rValue)
Definition: YiConcurrentDeque.h:152
void PushFront(const YI_DATA &rData)
Definition: YiConcurrentDeque.h:48
void WaitEmpty()
Definition: YiConcurrentDeque.h:72
bool Empty() const
Definition: YiConcurrentDeque.h:84
bool TryPopFront(YI_DATA &rValue)
Definition: YiConcurrentDeque.h:94
CYIConcurrentDeque & operator=(const CYIConcurrentDeque< YI_DATA > &rhs)
Definition: YiConcurrentDeque.h:37
A simple, thread safe deque.
Definition: YiConcurrentDeque.h:22
bool TryLock()
bool Wait(CYIMutex &rMutex)
uint32_t GetSize() const
Definition: YiConcurrentDeque.h:265
A class used to block a thread until a condition is met, as signaled by a different thread...
Definition: YiWaitCondition.h:64
bool WaitAndPopBack(YI_DATA &rValue)
Definition: YiConcurrentDeque.h:219
Definition: YiAutoMutex.h:23