| #ifndef OPENPOSE_THREAD_THREAD_HPP |
| #define OPENPOSE_THREAD_THREAD_HPP |
|
|
| #include <atomic> |
| #include <openpose/core/common.hpp> |
| #include <openpose/thread/subThread.hpp> |
| #include <openpose/thread/worker.hpp> |
|
|
| namespace op |
| { |
| template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>> |
| class Thread |
| { |
| public: |
| explicit Thread(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr = nullptr); |
|
|
| |
| Thread(Thread&& t); |
|
|
| |
| Thread& operator=(Thread&& t); |
|
|
| |
| virtual ~Thread(); |
|
|
| void add(const std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>& subThreads); |
|
|
| void add(const std::shared_ptr<SubThread<TDatums, TWorker>>& subThread); |
|
|
| void exec(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr); |
|
|
| void startInThread(); |
|
|
| void stopAndJoin(); |
|
|
| inline bool isRunning() const |
| { |
| return *spIsRunning; |
| } |
|
|
| private: |
| std::shared_ptr<std::atomic<bool>> spIsRunning; |
| std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>> mSubThreads; |
| std::thread mThread; |
|
|
| void initializationOnThread(); |
|
|
| void threadFunction(); |
|
|
| void stop(); |
|
|
| void join(); |
|
|
| DELETE_COPY(Thread); |
| }; |
| } |
|
|
|
|
|
|
|
|
|
|
| |
| namespace op |
| { |
| template<typename TDatums, typename TWorker> |
| Thread<TDatums, TWorker>::Thread(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr) : |
| spIsRunning{(isRunningSharedPtr != nullptr ? isRunningSharedPtr : std::make_shared<std::atomic<bool>>(false))} |
| { |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| Thread<TDatums, TWorker>::Thread(Thread<TDatums, TWorker>&& t) : |
| spIsRunning{std::make_shared<std::atomic<bool>>(t.spIsRunning->load())} |
| { |
| std::swap(mSubThreads, t.mSubThreads); |
| std::swap(mThread, t.mThread); |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| Thread<TDatums, TWorker>& Thread<TDatums, TWorker>::operator=(Thread<TDatums, TWorker>&& t) |
| { |
| std::swap(mSubThreads, t.mSubThreads); |
| std::swap(mThread, t.mThread); |
| spIsRunning = {std::make_shared<std::atomic<bool>>(t.spIsRunning->load())}; |
| return *this; |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| Thread<TDatums, TWorker>::~Thread() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| stopAndJoin(); |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| } |
| catch (const std::exception& e) |
| { |
| errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::add(const std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>& subThreads) |
| { |
| for (const auto& subThread : subThreads) |
| mSubThreads.emplace_back(subThread); |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::add(const std::shared_ptr<SubThread<TDatums, TWorker>>& subThread) |
| { |
| add(std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>{subThread}); |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::exec(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr) |
| { |
| try |
| { |
| stopAndJoin(); |
| spIsRunning = isRunningSharedPtr; |
| *spIsRunning = true; |
| threadFunction(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::startInThread() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| stopAndJoin(); |
| *spIsRunning = true; |
| mThread = {std::thread{&Thread::threadFunction, this}}; |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::stopAndJoin() |
| { |
| try |
| { |
| stop(); |
| join(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::initializationOnThread() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| for (auto& subThread : mSubThreads) |
| subThread->initializationOnThread(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::threadFunction() |
| { |
| try |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| initializationOnThread(); |
|
|
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| while (isRunning()) |
| { |
| bool allSubThreadsClosed = true; |
| for (auto& subThread : mSubThreads) |
| allSubThreadsClosed &= !subThread->work(); |
|
|
| if (allSubThreadsClosed) |
| { |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| stop(); |
| break; |
| } |
| } |
| opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::stop() |
| { |
| try |
| { |
| *spIsRunning = false; |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| template<typename TDatums, typename TWorker> |
| void Thread<TDatums, TWorker>::join() |
| { |
| try |
| { |
| if (mThread.joinable()) |
| mThread.join(); |
| } |
| catch (const std::exception& e) |
| { |
| error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
| } |
| } |
|
|
| COMPILE_TEMPLATE_DATUM(Thread); |
| } |
|
|
| #endif |
|
|