| #ifndef OPENPOSE_THREAD_QUEUE_BASE_HPP |
| #define OPENPOSE_THREAD_QUEUE_BASE_HPP |
|
|
| #include <condition_variable> |
| #include <mutex> |
| #include <queue> |
| #include <openpose/core/common.hpp> |
|
|
| namespace op |
| { |
| template<typename TDatums, typename TQueue> |
| class QueueBase |
| { |
| public: |
| explicit QueueBase(const long long maxSize = -1); |
|
|
| virtual ~QueueBase(); |
|
|
| bool forceEmplace(TDatums& tDatums); |
|
|
| bool tryEmplace(TDatums& tDatums); |
|
|
| bool waitAndEmplace(TDatums& tDatums); |
|
|
| bool forcePush(const TDatums& tDatums); |
|
|
| bool tryPush(const TDatums& tDatums); |
|
|
| bool waitAndPush(const TDatums& tDatums); |
|
|
| bool tryPop(TDatums& tDatums); |
|
|
| bool tryPop(); |
|
|
| bool waitAndPop(TDatums& tDatums); |
|
|
| bool waitAndPop(); |
|
|
| bool empty() const; |
|
|
| void stop(); |
|
|
| void stopPusher(); |
|
|
| void addPopper(); |
|
|
| void addPusher(); |
|
|
| bool isRunning() const; |
|
|
| bool isFull() const; |
|
|
| size_t size() const; |
|
|
| void clear(); |
|
|
| virtual TDatums front() const = 0; |
|
|
| protected: |
| mutable std::mutex mMutex; |
| long long mPoppers; |
| long long mPushers; |
| long long mMaxPoppersPushers; |
| bool mPopIsStopped; |
| bool mPushIsStopped; |
| std::condition_variable mConditionVariable; |
| TQueue mTQueue; |
|
|
| virtual bool pop(TDatums& tDatums) = 0; |
|
|
| unsigned long long getMaxSize() const; |
|
|
| private: |
| const long long mMaxSize; |
|
|
| bool emplace(TDatums& tDatums); |
|
|
| bool push(const TDatums& tDatums); |
|
|
| bool pop(); |
|
|
| void updateMaxPoppersPushers(); |
|
|
| DELETE_COPY(QueueBase); |
| }; |
| } |
|
|
|
|
|
|
|
|
|
|
| |
| #include <openpose/core/datum.hpp> |
| #include <openpose/utilities/fastMath.hpp> |
| namespace op |
| { |
| template<typename TDatums, typename TQueue> |
| QueueBase<TDatums, TQueue>::QueueBase(const long long maxSize) : |
| mPoppers{0ll}, |
| mPushers{0ll}, |
| mPopIsStopped{false}, |
| mPushIsStopped{false}, |
| mMaxSize{maxSize} |
| { |
| } |
|
|
| |
| template<typename TDatums, typename TQueue> |
| QueueBase<TDatums, TQueue>::~QueueBase() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| stop(); |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::forceEmplace(TDatums& tDatums) |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| if (mTQueue.size() >= getMaxSize()) |
| mTQueue.pop(); |
| return emplace(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::tryEmplace(TDatums& tDatums) |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| if (mTQueue.size() >= getMaxSize()) |
| return false; |
| return emplace(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::waitAndEmplace(TDatums& tDatums) |
| { |
| try |
| { |
| std::unique_lock<std::mutex> lock{mMutex}; |
| mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; }); |
| return emplace(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::forcePush(const TDatums& tDatums) |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| if (mTQueue.size() >= getMaxSize()) |
| mTQueue.pop(); |
| return push(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::tryPush(const TDatums& tDatums) |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| if (mTQueue.size() >= getMaxSize()) |
| return false; |
| return push(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::waitAndPush(const TDatums& tDatums) |
| { |
| try |
| { |
| std::unique_lock<std::mutex> lock{mMutex}; |
| mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; }); |
| return push(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::tryPop(TDatums& tDatums) |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| return pop(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::tryPop() |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| return pop(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::waitAndPop(TDatums& tDatums) |
| { |
| try |
| { |
| std::unique_lock<std::mutex> lock{mMutex}; |
| mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; }); |
| return pop(tDatums); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::waitAndPop() |
| { |
| try |
| { |
| std::unique_lock<std::mutex> lock{mMutex}; |
| mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; }); |
| return pop(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::empty() const |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| return mTQueue.empty(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::stop() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| mPopIsStopped = {true}; |
| mPushIsStopped = {true}; |
| while (!mTQueue.empty()) |
| mTQueue.pop(); |
| mConditionVariable.notify_all(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::stopPusher() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| mPushers--; |
| if (mPushers == 0) |
| { |
| mPushIsStopped = {true}; |
| if (mTQueue.empty()) |
| mPopIsStopped = {true}; |
| mConditionVariable.notify_all(); |
| } |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::addPopper() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| mPoppers++; |
| updateMaxPoppersPushers(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::addPusher() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| mPushers++; |
| updateMaxPoppersPushers(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::isRunning() const |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| return !(mPushIsStopped && (mPopIsStopped || mTQueue.empty())); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return true; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::isFull() const |
| { |
| try |
| { |
| |
| return size() == getMaxSize(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| size_t QueueBase<TDatums, TQueue>::size() const |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| return mTQueue.size(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return 0; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::clear() |
| { |
| try |
| { |
| const std::lock_guard<std::mutex> lock{mMutex}; |
| while (!mTQueue.empty()) |
| mTQueue.pop(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| unsigned long long QueueBase<TDatums, TQueue>::getMaxSize() const |
| { |
| try |
| { |
| return (mMaxSize > 0 ? mMaxSize : fastMax(1ll, mMaxPoppersPushers)); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::emplace(TDatums& tDatums) |
| { |
| try |
| { |
| if (mPushIsStopped) |
| return false; |
|
|
| mTQueue.emplace(tDatums); |
| mConditionVariable.notify_all(); |
| return true; |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::push(const TDatums& tDatums) |
| { |
| try |
| { |
| if (mPushIsStopped) |
| return false; |
|
|
| mTQueue.push(tDatums); |
| mConditionVariable.notify_all(); |
| return true; |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| bool QueueBase<TDatums, TQueue>::pop() |
| { |
| try |
| { |
| if (mPopIsStopped || mTQueue.empty()) |
| return false; |
|
|
| mTQueue.pop(); |
| mConditionVariable.notify_all(); |
| return true; |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| return false; |
| } |
| } |
|
|
| template<typename TDatums, typename TQueue> |
| void QueueBase<TDatums, TQueue>::updateMaxPoppersPushers() |
| { |
| try |
| { |
| mMaxPoppersPushers = fastMax(mPoppers, mPushers); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| extern template class QueueBase<BASE_DATUMS_SH, std::queue<BASE_DATUMS_SH>>; |
| extern template class QueueBase< |
| BASE_DATUMS_SH, |
| std::priority_queue<BASE_DATUMS_SH, std::vector<BASE_DATUMS_SH>, |
| std::greater<BASE_DATUMS_SH>>>; |
| } |
|
|
| #endif |
|
|