TrinityCore
ProducerConsumerQueue.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
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 TRINITY_PRODUCER_CONSUMER_QUEUE_H
19#define TRINITY_PRODUCER_CONSUMER_QUEUE_H
20
21#include <condition_variable>
22#include <mutex>
23#include <queue>
24#include <atomic>
25#include <type_traits>
26
27template <typename T>
29{
30private:
31 mutable std::mutex _queueLock;
32 std::queue<T> _queue;
33 std::condition_variable _condition;
34 std::atomic<bool> _shutdown;
35
36public:
37
39
40 void Push(T const& value)
41 {
42 std::lock_guard<std::mutex> lock(_queueLock);
43 _queue.push(value);
44
45 _condition.notify_one();
46 }
47
48 void Push(T&& value)
49 {
50 std::lock_guard<std::mutex> lock(_queueLock);
51 _queue.push(std::move(value));
52
53 _condition.notify_one();
54 }
55
56 bool Empty() const
57 {
58 std::lock_guard<std::mutex> lock(_queueLock);
59
60 return _queue.empty();
61 }
62
63 size_t Size() const
64 {
65 std::lock_guard<std::mutex> lock(_queueLock);
66
67 return _queue.size();
68 }
69
70 bool Pop(T& value)
71 {
72 std::lock_guard<std::mutex> lock(_queueLock);
73
74 if (_queue.empty() || _shutdown)
75 return false;
76
77 value = std::move(_queue.front());
78
79 _queue.pop();
80
81 return true;
82 }
83
84 void WaitAndPop(T& value)
85 {
86 std::unique_lock<std::mutex> lock(_queueLock);
87
88 // we could be using .wait(lock, predicate) overload here but it is broken
89 // https://connect.microsoft.com/VisualStudio/feedback/details/1098841
90 while (_queue.empty() && !_shutdown)
91 _condition.wait(lock);
92
93 if (_queue.empty() || _shutdown)
94 return;
95
96 value = _queue.front();
97
98 _queue.pop();
99 }
100
101 void Cancel()
102 {
103 std::unique_lock<std::mutex> lock(_queueLock);
104
105 while (!_queue.empty())
106 {
107 T& value = _queue.front();
108
109 if constexpr (std::is_pointer_v<T>)
110 delete value;
111
112 _queue.pop();
113 }
114
115 _shutdown = true;
116
117 _condition.notify_all();
118 }
119};
120
121#endif // TRINITY_PRODUCER_CONSUMER_QUEUE_H
std::atomic< bool > _shutdown
void Push(T const &value)
std::condition_variable _condition