TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ProducerConsumerQueue.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _PCQ_H
19 #define _PCQ_H
20 
21 #include <condition_variable>
22 #include <mutex>
23 #include <queue>
24 #include <atomic>
25 #include <type_traits>
26 
27 template <typename T>
29 {
30 private:
31  std::mutex _queueLock;
32  std::queue<T> _queue;
33  std::condition_variable _condition;
34  std::atomic<bool> _shutdown;
35 
36 public:
37 
39 
40  void Push(const T& value)
41  {
42  std::lock_guard<std::mutex> lock(_queueLock);
43  _queue.push(std::move(value));
44 
45  _condition.notify_one();
46  }
47 
48  bool Empty()
49  {
50  std::lock_guard<std::mutex> lock(_queueLock);
51 
52  return _queue.empty();
53  }
54 
55  bool Pop(T& value)
56  {
57  std::lock_guard<std::mutex> lock(_queueLock);
58 
59  if (_queue.empty() || _shutdown)
60  return false;
61 
62  value = _queue.front();
63 
64  _queue.pop();
65 
66  return true;
67  }
68 
69  void WaitAndPop(T& value)
70  {
71  std::unique_lock<std::mutex> lock(_queueLock);
72 
73  // we could be using .wait(lock, predicate) overload here but it is broken
74  // https://connect.microsoft.com/VisualStudio/feedback/details/1098841
75  while (_queue.empty() && !_shutdown)
76  _condition.wait(lock);
77 
78  if (_queue.empty() || _shutdown)
79  return;
80 
81  value = _queue.front();
82 
83  _queue.pop();
84  }
85 
86  void Cancel()
87  {
88  std::unique_lock<std::mutex> lock(_queueLock);
89 
90  while (!_queue.empty())
91  {
92  T& value = _queue.front();
93 
94  DeleteQueuedObject(value);
95 
96  _queue.pop();
97  }
98 
99  _shutdown = true;
100 
101  _condition.notify_all();
102  }
103 
104 private:
105  template<typename E = T>
106  typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; }
107 
108  template<typename E = T>
109  typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { }
110 };
111 
112 #endif
std::condition_variable _condition
Definition: ProducerConsumerQueue.h:33
Definition: ProducerConsumerQueue.h:28
std::mutex _queueLock
Definition: ProducerConsumerQueue.h:31
bool Pop(T &value)
Definition: ProducerConsumerQueue.h:55
std::queue< T > _queue
Definition: ProducerConsumerQueue.h:32
std::enable_if<!std::is_pointer< E >::value >::type DeleteQueuedObject(E const &)
Definition: ProducerConsumerQueue.h:109
void WaitAndPop(T &value)
Definition: ProducerConsumerQueue.h:69
std::enable_if< std::is_pointer< E >::value >::type DeleteQueuedObject(E &obj)
Definition: ProducerConsumerQueue.h:106
std::atomic< bool > _shutdown
Definition: ProducerConsumerQueue.h:34
void Push(const T &value)
Definition: ProducerConsumerQueue.h:40
void Cancel()
Definition: ProducerConsumerQueue.h:86
const FieldDescriptor value
Definition: descriptor.h:1522
bool Empty()
Definition: ProducerConsumerQueue.h:48