| #ifndef OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP |
| #define OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP |
|
|
| #include <queue> |
| #include <openpose/core/common.hpp> |
| #include <openpose/thread/worker.hpp> |
| #include <openpose/utilities/pointerContainer.hpp> |
|
|
| namespace op |
| { |
| template<typename TDatums> |
| class WQueueOrderer : public Worker<TDatums> |
| { |
| public: |
| explicit WQueueOrderer(const unsigned int maxBufferSize = 64u); |
|
|
| virtual ~WQueueOrderer(); |
|
|
| void initializationOnThread(); |
|
|
| void work(TDatums& tDatums); |
|
|
| void tryStop(); |
|
|
| private: |
| const unsigned int mMaxBufferSize; |
| bool mStopWhenEmpty; |
| unsigned long long mNextExpectedId; |
| unsigned long long mNextExpectedSubId; |
| std::priority_queue<TDatums, std::vector<TDatums>, PointerContainerGreater<TDatums>> mPriorityQueueBuffer; |
|
|
| DELETE_COPY(WQueueOrderer); |
| }; |
| } |
|
|
|
|
|
|
|
|
|
|
| |
| namespace op |
| { |
| template<typename TDatums> |
| WQueueOrderer<TDatums>::WQueueOrderer(const unsigned int maxBufferSize) : |
| mMaxBufferSize{maxBufferSize}, |
| mStopWhenEmpty{false}, |
| mNextExpectedId{0}, |
| mNextExpectedSubId{0} |
| { |
| } |
|
|
| template<typename TDatums> |
| WQueueOrderer<TDatums>::~WQueueOrderer() |
| { |
| } |
|
|
| template<typename TDatums> |
| void WQueueOrderer<TDatums>::initializationOnThread() |
| { |
| } |
|
|
| template<typename TDatums> |
| void WQueueOrderer<TDatums>::work(TDatums& tDatums) |
| { |
| try |
| { |
| |
| const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); |
| bool profileSpeed = (tDatums != nullptr); |
| |
| if (checkNoNullNorEmpty(tDatums)) |
| { |
| |
| auto& tDatumsNoPtr = *tDatums; |
| |
| if (tDatumsNoPtr[0]->id == mNextExpectedId && tDatumsNoPtr[0]->subId == mNextExpectedSubId) |
| { |
| |
| if (tDatumsNoPtr[0]->subIdMax == 0) |
| mNextExpectedId++; |
| |
| else |
| { |
| mNextExpectedSubId++; |
| if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax) |
| { |
| mNextExpectedSubId = 0; |
| mNextExpectedId++; |
| } |
| } |
| } |
| |
| else |
| { |
| |
| mPriorityQueueBuffer.emplace(tDatums); |
| tDatums = nullptr; |
| |
| if (mPriorityQueueBuffer.size() > mMaxBufferSize) |
| { |
| tDatums = mPriorityQueueBuffer.top(); |
| mPriorityQueueBuffer.pop(); |
| } |
| } |
| } |
| |
| if (!checkNoNullNorEmpty(tDatums)) |
| { |
| |
| if (!mPriorityQueueBuffer.empty() |
| && (mStopWhenEmpty || |
| ((*mPriorityQueueBuffer.top())[0]->id == mNextExpectedId |
| && (*mPriorityQueueBuffer.top())[0]->subId == mNextExpectedSubId))) |
| { |
| tDatums = { mPriorityQueueBuffer.top() }; |
| mPriorityQueueBuffer.pop(); |
| } |
| } |
| |
| if (checkNoNullNorEmpty(tDatums)) |
| { |
| const auto& tDatumsNoPtr = *tDatums; |
| |
| if (tDatumsNoPtr[0]->subIdMax == 0) |
| mNextExpectedId = tDatumsNoPtr[0]->id + 1; |
| |
| else |
| { |
| mNextExpectedSubId = tDatumsNoPtr[0]->subId + 1; |
| if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax) |
| { |
| mNextExpectedSubId = 0; |
| mNextExpectedId = tDatumsNoPtr[0]->id + 1; |
| } |
| } |
| } |
| |
| if (!checkNoNullNorEmpty(tDatums) && mPriorityQueueBuffer.size() < mMaxBufferSize / 2u) |
| std::this_thread::sleep_for(std::chrono::milliseconds{1}); |
| |
| if (profileSpeed || tDatums != nullptr) |
| { |
| |
| Profiler::timerEnd(profilerKey); |
| Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); |
| |
| opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
| catch (const std::exception& e) |
| { |
| this->stop(); |
| tDatums = nullptr; |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums> |
| void WQueueOrderer<TDatums>::tryStop() |
| { |
| try |
| { |
| |
| if (mPriorityQueueBuffer.empty()) |
| this->stop(); |
| mStopWhenEmpty = true; |
|
|
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| COMPILE_TEMPLATE_DATUM(WQueueOrderer); |
| } |
|
|
| #endif |
|
|