diff options
Diffstat (limited to 'src/base/WorkerThread.h')
-rw-r--r-- | src/base/WorkerThread.h | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/base/WorkerThread.h b/src/base/WorkerThread.h new file mode 100644 index 0000000..c4cc3c4 --- /dev/null +++ b/src/base/WorkerThread.h @@ -0,0 +1,169 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _WorkerThread_H_ +#define _WorkerThread_H_ + +#include "../api.h" +#include "Command.h" +#include "Exception.h" +#include "Logger.h" +#include "Queue.h" +#include "ThreadHelper.h" +#include "ThreadProfiler.h" +#include "CmdQueue.h" + +#include <boost/shared_ptr.hpp> + +#include <iostream> + +namespace avg { + + +template<class DERIVED_THREAD> +class AVG_TEMPLATE_API WorkerThread { +public: + typedef Command<DERIVED_THREAD> Cmd; + typedef typename boost::shared_ptr<Cmd> CmdPtr; + typedef CmdQueue<DERIVED_THREAD> CQueue; + typedef typename boost::shared_ptr<CQueue> CQueuePtr; + + WorkerThread(const std::string& sName, CQueue& CmdQ, + category_t logCategory=Logger::category::PROFILE); + WorkerThread(WorkerThread const& other); + virtual ~WorkerThread(); + void operator()(); + + void waitForCommand(); + void stop(); + +protected: + int getNumCmdsInQueue() const; + +private: + virtual bool init(); + virtual bool work() = 0; + virtual void deinit() {}; + + void processCommands(); + + std::string m_sName; + bool m_bShouldStop; + CQueue& m_CmdQ; + category_t m_LogCategory; +}; + +template<class DERIVED_THREAD> +WorkerThread<DERIVED_THREAD>::WorkerThread(const std::string& sName, CQueue& CmdQ, + category_t logCategory) + : m_sName(sName), + m_bShouldStop(false), + m_CmdQ(CmdQ), + m_LogCategory(logCategory) +{ +} + +template<class DERIVED_THREAD> +WorkerThread<DERIVED_THREAD>::WorkerThread(WorkerThread const& other) + : m_CmdQ(other.m_CmdQ) +{ + m_sName = other.m_sName; + m_bShouldStop = other.m_bShouldStop; + m_LogCategory = other.m_LogCategory; +} + +template<class DERIVED_THREAD> +WorkerThread<DERIVED_THREAD>::~WorkerThread() +{ +} + +template<class DERIVED_THREAD> +void WorkerThread<DERIVED_THREAD>::operator()() +{ + try { + setAffinityMask(false); + ThreadProfiler* pProfiler = ThreadProfiler::get(); + pProfiler->setName(m_sName); + pProfiler->setLogCategory(m_LogCategory); + bool bOK; + bOK = init(); + if (!bOK) { + return; + } + pProfiler->start(); + while (!m_bShouldStop) { + bOK = work(); + if (!bOK) { + m_bShouldStop = true; + } + if (!m_bShouldStop) { + processCommands(); + } + } + deinit(); + pProfiler->dumpStatistics(); + pProfiler->kill(); + } catch (const Exception& e) { + AVG_LOG_ERROR("Uncaught exception in thread " << m_sName << ": " << e.getStr()); + throw; + } +} + +template<class DERIVED_THREAD> +void WorkerThread<DERIVED_THREAD>::waitForCommand() +{ + CmdPtr pCmd = m_CmdQ.pop(true); + pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this)); +} + +template<class DERIVED_THREAD> +void WorkerThread<DERIVED_THREAD>::stop() +{ + m_bShouldStop = true; +} + +template<class DERIVED_THREAD> +int WorkerThread<DERIVED_THREAD>::getNumCmdsInQueue() const +{ + return m_CmdQ.size(); +} + +template<class DERIVED_THREAD> +bool WorkerThread<DERIVED_THREAD>::init() +{ + return true; +} + +template<class DERIVED_THREAD> +void WorkerThread<DERIVED_THREAD>::processCommands() +{ + CmdPtr pCmd = m_CmdQ.pop(false); + while (pCmd && !m_bShouldStop) { + pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this)); + if (!m_bShouldStop) { + pCmd = m_CmdQ.pop(false); + } + } +} + +} + +#endif |