├── main.cpp ├── README.md ├── LICENSE └── SafeQueue.hpp /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * main.cpp 3 | * Copyright (C) 2019 Alfredo Pons Menargues 4 | * 5 | * This program is free software: you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | * See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | int main() 22 | { 23 | SafeQueue my_queue; 24 | 25 | my_queue.push(1); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # queue-thread-safe 2 | 3 | A thread-safe asynchronous queue in C++11 inspired in glib asynchronous queue (https://developer.gnome.org/glib/2.50/glib-Asynchronous-Queues.html) 4 | 5 | 6 | 7 | ## License 8 | 9 | The LGPL License (LGPL-3+) 10 | 11 | Copyright (c) 2019 Alfredo Pons - apons@linucleus.com 12 | 13 | This program is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as published by 15 | the Free Software Foundation, either version 3 of the License, or 16 | (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program. If not, see . 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /SafeQueue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SafeQueue.hpp 3 | * Copyright (C) 2019 Alfredo Pons Menargues 4 | * 5 | * This program is free software: you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | * See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program. If not, see . 17 | */ 18 | #ifndef SAFEQUEUE_HPP_ 19 | #define SAFEQUEUE_HPP_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | 30 | /** A thread-safe asynchronous queue */ 31 | template > 32 | class SafeQueue 33 | { 34 | 35 | typedef typename Container::value_type value_type; 36 | typedef typename Container::size_type size_type; 37 | typedef Container container_type; 38 | 39 | public: 40 | 41 | /*! Create safe queue. */ 42 | SafeQueue() = default; 43 | SafeQueue (SafeQueue&& sq) 44 | { 45 | m_queue = std::move (sq.m_queue); 46 | } 47 | SafeQueue (const SafeQueue& sq) 48 | { 49 | std::lock_guard lock (sq.m_mutex); 50 | m_queue = sq.m_queue; 51 | } 52 | 53 | /*! Destroy safe queue. */ 54 | ~SafeQueue() 55 | { 56 | std::lock_guard lock (m_mutex); 57 | } 58 | 59 | /** 60 | * Sets the maximum number of items in the queue. Defaults is 0: No limit 61 | * \param[in] item An item. 62 | */ 63 | void set_max_num_items (unsigned int max_num_items) 64 | { 65 | m_max_num_items = max_num_items; 66 | } 67 | 68 | /** 69 | * Pushes the item into the queue. 70 | * \param[in] item An item. 71 | * \return true if an item was pushed into the queue 72 | */ 73 | bool push (const value_type& item) 74 | { 75 | std::lock_guard lock (m_mutex); 76 | 77 | if (m_max_num_items > 0 && m_queue.size() > m_max_num_items) 78 | return false; 79 | 80 | m_queue.push (item); 81 | m_condition.notify_one(); 82 | return true; 83 | } 84 | 85 | /** 86 | * Pushes the item into the queue. 87 | * \param[in] item An item. 88 | * \return true if an item was pushed into the queue 89 | */ 90 | bool push (const value_type&& item) 91 | { 92 | std::lock_guard lock (m_mutex); 93 | 94 | if (m_max_num_items > 0 && m_queue.size() > m_max_num_items) 95 | return false; 96 | 97 | m_queue.push (item); 98 | m_condition.notify_one(); 99 | return true; 100 | } 101 | 102 | /** 103 | * Pops item from the queue. If queue is empty, this function blocks until item becomes available. 104 | * \param[out] item The item. 105 | */ 106 | void pop (value_type& item) 107 | { 108 | std::unique_lock lock (m_mutex); 109 | m_condition.wait (lock, [this]() // Lambda funct 110 | { 111 | return !m_queue.empty(); 112 | }); 113 | item = m_queue.front(); 114 | m_queue.pop(); 115 | } 116 | 117 | /** 118 | * Pops item from the queue using the contained type's move assignment operator, if it has one.. 119 | * This method is identical to the pop() method if that type has no move assignment operator. 120 | * If queue is empty, this function blocks until item becomes available. 121 | * \param[out] item The item. 122 | */ 123 | void move_pop (value_type& item) 124 | { 125 | std::unique_lock lock (m_mutex); 126 | m_condition.wait (lock, [this]() // Lambda funct 127 | { 128 | return !m_queue.empty(); 129 | }); 130 | item = std::move (m_queue.front()); 131 | m_queue.pop(); 132 | } 133 | 134 | /** 135 | * Tries to pop item from the queue. 136 | * \param[out] item The item. 137 | * \return False is returned if no item is available. 138 | */ 139 | bool try_pop (value_type& item) 140 | { 141 | std::unique_lock lock (m_mutex); 142 | 143 | if (m_queue.empty()) 144 | return false; 145 | 146 | item = m_queue.front(); 147 | m_queue.pop(); 148 | return true; 149 | } 150 | 151 | /** 152 | * Tries to pop item from the queue using the contained type's move assignment operator, if it has one.. 153 | * This method is identical to the try_pop() method if that type has no move assignment operator. 154 | * \param[out] item The item. 155 | * \return False is returned if no item is available. 156 | */ 157 | bool try_move_pop (value_type& item) 158 | { 159 | std::unique_lock lock (m_mutex); 160 | 161 | if (m_queue.empty()) 162 | return false; 163 | 164 | item = std::move (m_queue.front()); 165 | m_queue.pop(); 166 | return true; 167 | } 168 | 169 | /** 170 | * Pops item from the queue. If the queue is empty, blocks for timeout microseconds, or until item becomes available. 171 | * \param[out] t An item. 172 | * \param[in] timeout The number of microseconds to wait. 173 | * \return true if get an item from the queue, false if no item is received before the timeout. 174 | */ 175 | bool timeout_pop (value_type& item, std::uint64_t timeout) 176 | { 177 | std::unique_lock lock (m_mutex); 178 | 179 | if (m_queue.empty()) 180 | { 181 | if (timeout == 0) 182 | return false; 183 | 184 | if (m_condition.wait_for (lock, std::chrono::microseconds (timeout)) == std::cv_status::timeout) 185 | return false; 186 | } 187 | 188 | item = m_queue.front(); 189 | m_queue.pop(); 190 | return true; 191 | } 192 | 193 | /** 194 | * Pops item from the queue using the contained type's move assignment operator, if it has one.. 195 | * If the queue is empty, blocks for timeout microseconds, or until item becomes available. 196 | * This method is identical to the try_pop() method if that type has no move assignment operator. 197 | * \param[out] t An item. 198 | * \param[in] timeout The number of microseconds to wait. 199 | * \return true if get an item from the queue, false if no item is received before the timeout. 200 | */ 201 | bool timeout_move_pop (value_type& item, std::uint64_t timeout) 202 | { 203 | std::unique_lock lock (m_mutex); 204 | 205 | if (m_queue.empty()) 206 | { 207 | if (timeout == 0) 208 | return false; 209 | 210 | if (m_condition.wait_for (lock, std::chrono::microseconds (timeout)) == std::cv_status::timeout) 211 | return false; 212 | } 213 | 214 | item = std::move (m_queue.front()); 215 | m_queue.pop(); 216 | return true; 217 | } 218 | 219 | /** 220 | * Gets the number of items in the queue. 221 | * \return Number of items in the queue. 222 | */ 223 | size_type size() const 224 | { 225 | std::lock_guard lock (m_mutex); 226 | return m_queue.size(); 227 | } 228 | 229 | /** 230 | * Check if the queue is empty. 231 | * \return true if queue is empty. 232 | */ 233 | bool empty() const 234 | { 235 | std::lock_guard lock (m_mutex); 236 | return m_queue.empty(); 237 | } 238 | 239 | /** 240 | * Swaps the contents. 241 | * \param[out] sq The SafeQueue to swap with 'this'. 242 | */ 243 | void swap (SafeQueue& sq) 244 | { 245 | if (this != &sq) 246 | { 247 | std::lock_guard lock1 (m_mutex); 248 | std::lock_guard lock2 (sq.m_mutex); 249 | m_queue.swap (sq.m_queue); 250 | 251 | if (!m_queue.empty()) 252 | m_condition.notify_all(); 253 | 254 | if (!sq.m_queue.empty()) 255 | sq.m_condition.notify_all(); 256 | } 257 | } 258 | 259 | /*! The copy assignment operator */ 260 | SafeQueue& operator= (const SafeQueue& sq) 261 | { 262 | if (this != &sq) 263 | { 264 | std::lock_guard lock1 (m_mutex); 265 | std::lock_guard lock2 (sq.m_mutex); 266 | std::queue temp {sq.m_queue}; 267 | m_queue.swap (temp); 268 | 269 | if (!m_queue.empty()) 270 | m_condition.notify_all(); 271 | } 272 | 273 | return *this; 274 | } 275 | 276 | /*! The move assignment operator */ 277 | SafeQueue& operator= (SafeQueue && sq) 278 | { 279 | std::lock_guard lock (m_mutex); 280 | m_queue = std::move (sq.m_queue); 281 | 282 | if (!m_queue.empty()) m_condition.notify_all(); 283 | 284 | return *this; 285 | } 286 | 287 | 288 | private: 289 | 290 | std::queue m_queue; 291 | mutable std::mutex m_mutex; 292 | std::condition_variable m_condition; 293 | unsigned int m_max_num_items = 0; 294 | }; 295 | 296 | /*! Swaps the contents of two SafeQueue objects. */ 297 | template 298 | void swap (SafeQueue& q1, SafeQueue& q2) 299 | { 300 | q1.swap (q2); 301 | } 302 | #endif /* SAFEQUEUE_HPP_ */ 303 | --------------------------------------------------------------------------------