/* * BlockingQueue.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "StdInc.h" VCMI_LIB_NAMESPACE_BEGIN //Credit to https://github.com/Liam0205/toy-threadpool/tree/master/yuuki template <typename T> class DLL_LINKAGE BlockingQueue : protected std::queue<T> { using WriteLock = boost::unique_lock<boost::shared_mutex>; using Readlock = boost::shared_lock<boost::shared_mutex>; public: BlockingQueue() = default; ~BlockingQueue() { clear(); } BlockingQueue(const BlockingQueue&) = delete; BlockingQueue(BlockingQueue&&) = delete; BlockingQueue& operator=(const BlockingQueue&) = delete; BlockingQueue& operator=(BlockingQueue&&) = delete; public: bool empty() const { Readlock lock(mx); return std::queue<T>::empty(); } size_t size() const { Readlock lock(mx); return std::queue<T>::size(); } public: void clear() { WriteLock lock(mx); while (!std::queue<T>::empty()) { std::queue<T>::pop(); } } void push(const T& obj) { WriteLock lock(mx); std::queue<T>::push(obj); } template <typename... Args> void emplace(Args&&... args) { WriteLock lock(mx); std::queue<T>::emplace(std::forward<Args>(args)...); } bool pop(T& holder) { WriteLock lock(mx); if (std::queue<T>::empty()) { return false; } else { holder = std::move(std::queue<T>::front()); std::queue<T>::pop(); return true; } } private: mutable boost::shared_mutex mx; }; VCMI_LIB_NAMESPACE_END