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