#ifndef OPENPOSE_THREAD_THREAD_HPP #define OPENPOSE_THREAD_THREAD_HPP #include #include #include #include namespace op { template>> class Thread { public: explicit Thread(const std::shared_ptr>& isRunningSharedPtr = nullptr); // Move constructor Thread(Thread&& t); // Move assignment Thread& operator=(Thread&& t); // Destructor virtual ~Thread(); void add(const std::vector>>& subThreads); void add(const std::shared_ptr>& subThread); void exec(const std::shared_ptr>& isRunningSharedPtr); void startInThread(); void stopAndJoin(); inline bool isRunning() const { return *spIsRunning; } private: std::shared_ptr> spIsRunning; std::vector>> mSubThreads; std::thread mThread; void initializationOnThread(); void threadFunction(); void stop(); void join(); DELETE_COPY(Thread); }; } // Implementation namespace op { template Thread::Thread(const std::shared_ptr>& isRunningSharedPtr) : spIsRunning{(isRunningSharedPtr != nullptr ? isRunningSharedPtr : std::make_shared>(false))} { } template Thread::Thread(Thread&& t) : spIsRunning{std::make_shared>(t.spIsRunning->load())} { std::swap(mSubThreads, t.mSubThreads); std::swap(mThread, t.mThread); } template Thread& Thread::operator=(Thread&& t) { std::swap(mSubThreads, t.mSubThreads); std::swap(mThread, t.mThread); spIsRunning = {std::make_shared>(t.spIsRunning->load())}; return *this; } template Thread::~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 void Thread::add(const std::vector>>& subThreads) { for (const auto& subThread : subThreads) mSubThreads.emplace_back(subThread); } template void Thread::add(const std::shared_ptr>& subThread) { add(std::vector>>{subThread}); } template void Thread::exec(const std::shared_ptr>& isRunningSharedPtr) { try { stopAndJoin(); spIsRunning = isRunningSharedPtr; *spIsRunning = true; threadFunction(); } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } } template void Thread::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 void Thread::stopAndJoin() { try { stop(); join(); } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } } template void Thread::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 void Thread::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 void Thread::stop() { try { *spIsRunning = false; } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } } template void Thread::join() { try { if (mThread.joinable()) mThread.join(); } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } } COMPILE_TEMPLATE_DATUM(Thread); } #endif // OPENPOSE_THREAD_THREAD_HPP