Horizon Official Technical Documentation
ThreadSafeQueue.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 * This library is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this library. If not, see <http://www.gnu.org/licenses/>.
26 **************************************************/
27
28#ifndef HORIZON_CORE_MULTITHREADING_THREADSAFEQUEUE_HPP
29#define HORIZON_CORE_MULTITHREADING_THREADSAFEQUEUE_HPP
30
31#include <memory>
32#include <thread>
33#include <mutex>
34
35template<typename T>
37{
38private:
39 struct node
40 {
41 std::shared_ptr<T> data;
42 std::unique_ptr<node> next;
43 };
44
45 std::mutex head_mutex;
46 std::unique_ptr<node> head;
47 std::mutex tail_mutex;
49
51 {
52 std::unique_lock<std::mutex> tail_lock(tail_mutex);
53 return tail;
54 }
55
56 std::unique_ptr<node> pop_head()
57 {
58 std::unique_lock<std::mutex> head_lock(head_mutex);
59
60 if(head.get() == get_tail())
61 return nullptr;
62
63 std::unique_ptr<node> old_head = std::move(head);
64 head = std::move(old_head->next);
65 return old_head;
66 }
67
68public:
70 head(new node), tail(head.get())
71 {}
72
74 {
75 std::size_t qsize = size();
76
77 for (std::size_t i = 0; i < qsize; i++)
78 try_pop();
79 }
80
81 ThreadSafeQueue(const ThreadSafeQueue &other)=delete;
83
84 std::shared_ptr<T> try_pop()
85 {
86 std::unique_ptr<node> old_head = pop_head();
87 return old_head ? old_head->data : std::shared_ptr<T>();
88 }
89
90 void push(T &&new_value)
91 {
92 std::shared_ptr<T> new_data(
93 std::make_shared<T>(std::move(new_value)));
94 std::unique_ptr<node> p(new node);
95 node *new_tail = p.get();
96 std::unique_lock<std::mutex> tail_lock(tail_mutex);
97 tail->data = new_data;
98 tail->next = std::move(p);
99 tail = new_tail;
100 }
101
102 std::size_t size()
103 {
104 int count = 0;
105 std::unique_lock<std::mutex> head_lock(head_mutex);
106 std::unique_lock<std::mutex> tail_lock(tail_mutex);
107 node const *n = head.get();
108
109 while ((n = n->next.get())) {
110 count++;
111 }
112
113 return count;
114 }
115
116 bool empty()
117 {
118 std::unique_lock<std::mutex> head_lock(head_mutex);
119
120 if(head.get() == get_tail())
121 return true;
122
123 return false;
124 }
125
126 std::shared_ptr<T> front()
127 {
128 std::unique_lock<std::mutex> head_lock(head_mutex);
129 std::shared_ptr<T> front = head != nullptr ? std::make_shared<T>(*head->data) : nullptr;
130 return std::move(front);
131 }
132};
133
134#endif // HORIZON_CORE_MULTITHREADING_THREADSAFEQUEUE_HPP
Definition: ThreadSafeQueue.hpp:37
ThreadSafeQueue()
Definition: ThreadSafeQueue.hpp:69
ThreadSafeQueue(const ThreadSafeQueue &other)=delete
std::size_t size()
Definition: ThreadSafeQueue.hpp:102
bool empty()
Definition: ThreadSafeQueue.hpp:116
node * get_tail()
Definition: ThreadSafeQueue.hpp:50
std::mutex tail_mutex
Definition: ThreadSafeQueue.hpp:47
std::unique_ptr< node > pop_head()
Definition: ThreadSafeQueue.hpp:56
std::shared_ptr< T > front()
Definition: ThreadSafeQueue.hpp:126
ThreadSafeQueue & operator=(const ThreadSafeQueue &other)=delete
void push(T &&new_value)
Definition: ThreadSafeQueue.hpp:90
node * tail
Definition: ThreadSafeQueue.hpp:48
~ThreadSafeQueue()
Definition: ThreadSafeQueue.hpp:73
std::mutex head_mutex
Definition: ThreadSafeQueue.hpp:45
std::unique_ptr< node > head
Definition: ThreadSafeQueue.hpp:46
std::shared_ptr< T > try_pop()
Definition: ThreadSafeQueue.hpp:84
size_t count(GridTypeListContainer< SPECIFIC_TYPE > const &elements, SPECIFIC_TYPE *)
Definition: GridReferenceContainer.hpp:100
Definition: ThreadSafeQueue.hpp:40
std::shared_ptr< T > data
Definition: ThreadSafeQueue.hpp:41
std::unique_ptr< node > next
Definition: ThreadSafeQueue.hpp:42