Index: src/ch/ClipboardMonitor.cpp =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -20,7 +20,7 @@ /// @brief Contains the implementation of clipboard monitor package. //****************************************************************************** #include "stdafx.h" -#include "TWorkerThreadController.h" +#include "../libchcore/TWorkerThreadController.h" #include "ClipboardMonitor.h" #include "ch.h" #include "task.h" Index: src/ch/ClipboardMonitor.h =================================================================== diff -u -N -r92410cc8f6de1e1696774cb25cb37464c4e74cbd -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/ClipboardMonitor.h (.../ClipboardMonitor.h) (revision 92410cc8f6de1e1696774cb25cb37464c4e74cbd) +++ src/ch/ClipboardMonitor.h (.../ClipboardMonitor.h) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -45,7 +45,7 @@ CTaskArray* m_pTasks; // thread control - TWorkerThreadController m_threadWorker; + chcore::TWorkerThreadController m_threadWorker; }; #endif Index: src/ch/TSubTaskContext.cpp =================================================================== diff -u -N -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/TSubTaskContext.cpp (.../TSubTaskContext.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) +++ src/ch/TSubTaskContext.cpp (.../TSubTaskContext.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -25,7 +25,7 @@ TSubTaskContext::TSubTaskContext(chcore::TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats, TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, chcore::IFeedbackHandler* piFeedbackHandler, - TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal) : + chcore::TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal) : m_rTaskDefinition(rTaskDefinition), m_rBasePathDataContainer(rBasePathDataContainer), m_rFilesCache(rFilesCache), Index: src/ch/TSubTaskContext.h =================================================================== diff -u -N -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/TSubTaskContext.h (.../TSubTaskContext.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) +++ src/ch/TSubTaskContext.h (.../TSubTaskContext.h) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -29,9 +29,9 @@ { class IFeedbackHandler; class TTaskDefinition; + class TWorkerThreadController; } -class TWorkerThreadController; class TBasePathDataContainer; class TTaskLocalStats; class TTaskConfigTracker; @@ -46,7 +46,7 @@ public: TSubTaskContext(chcore::TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats, TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, - chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal); + chcore::IFeedbackHandler* piFeedbackHandler, chcore::TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal); ~TSubTaskContext(); chcore::TTaskDefinition& GetTaskDefinition() { return m_rTaskDefinition; } @@ -73,8 +73,8 @@ chcore::IFeedbackHandler* GetFeedbackHandler() { return m_piFeedbackHandler; } const chcore::IFeedbackHandler* GetFeedbackHandler() const { return m_piFeedbackHandler; } - TWorkerThreadController& GetThreadController() { return m_rThreadController; } - const TWorkerThreadController& GetThreadController() const { return m_rThreadController; } + chcore::TWorkerThreadController& GetThreadController() { return m_rThreadController; } + const chcore::TWorkerThreadController& GetThreadController() const { return m_rThreadController; } TLocalFilesystem& GetLocalFilesystem() { return m_rfsLocal; } const TLocalFilesystem& GetLocalFilesystem() const { return m_rfsLocal; } @@ -105,7 +105,7 @@ chcore::IFeedbackHandler* m_piFeedbackHandler; // thread control - TWorkerThreadController& m_rThreadController; + chcore::TWorkerThreadController& m_rThreadController; }; #endif // __TSUBTASKCONTEXT_H__ \ No newline at end of file Index: src/ch/TSubTaskCopyMove.cpp =================================================================== diff -u -N -r9a171c5d46f2bc029d99a698d88eeff60497cd3b -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 9a171c5d46f2bc029d99a698d88eeff60497cd3b) +++ src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -54,7 +54,7 @@ chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); TTaskConfigTracker& rCfgTracker = GetContext().GetCfgTracker(); TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo(); - TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + chcore::TWorkerThreadController& rThreadController = GetContext().GetThreadController(); chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); TTaskLocalStats& rLocalStats = GetContext().GetTaskLocalStats(); @@ -304,7 +304,7 @@ { chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo(); - TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + chcore::TWorkerThreadController& rThreadController = GetContext().GetThreadController(); TTaskLocalStats& rLocalStats = GetContext().GetTaskLocalStats(); icpf::log_file& rLog = GetContext().GetLog(); TTaskConfigTracker& rCfgTracker = GetContext().GetCfgTracker(); Index: src/ch/TSubTaskDelete.cpp =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -24,7 +24,7 @@ #include "TSubTaskDelete.h" #include "TSubTaskContext.h" #include "TBasicProgressInfo.h" -#include "TWorkerThreadController.h" +#include "../libchcore/TWorkerThreadController.h" #include "TTaskConfiguration.h" #include "../libchcore/TTaskDefinition.h" #include "FeedbackHandler.h" @@ -42,7 +42,7 @@ CFileInfoArray& rFilesCache = GetContext().GetFilesCache(); chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); TTaskBasicProgressInfo& rBasicProgressInfo = GetContext().GetTaskBasicProgressInfo(); - TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + chcore::TWorkerThreadController& rThreadController = GetContext().GetThreadController(); chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); // log Index: src/ch/TSubTaskScanDirectory.cpp =================================================================== diff -u -N -rb0d7cb2020371c35b5fbaab566b4dcc850fed460 -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision b0d7cb2020371c35b5fbaab566b4dcc850fed460) +++ src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -29,7 +29,7 @@ #include "TLocalFilesystem.h" #include "..\libchcore\FeedbackHandlerBase.h" #include "TBasePathData.h" -#include "TWorkerThreadController.h" +#include "../libchcore/TWorkerThreadController.h" #include "TTaskLocalStats.h" TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) : @@ -49,7 +49,7 @@ chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); const TBasePathDataContainer& rarrSourcePathsInfo = GetContext().GetBasePathDataContainer(); - TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + chcore::TWorkerThreadController& rThreadController = GetContext().GetThreadController(); rLog.logi(_T("Searching for files...")); @@ -217,7 +217,7 @@ { CFileInfoArray& rFilesCache = GetContext().GetFilesCache(); chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); - TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + chcore::TWorkerThreadController& rThreadController = GetContext().GetThreadController(); TLocalFilesystemFind finder = TLocalFilesystem::CreateFinderObject(pathDirName, chcore::PathFromString(_T("*"))); CFileInfoPtr spFileInfo(boost::make_shared()); Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -N -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -510,14 +510,6 @@ RelativePath=".\TTaskConfiguration.h" > - - - - Index: src/ch/task.h =================================================================== diff -u -N -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/ch/task.h (.../task.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) +++ src/ch/task.h (.../task.h) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -20,7 +20,7 @@ #define __TASK_H__ #include "TAutoHandles.h" -#include "TWorkerThreadController.h" +#include "../libchcore/TWorkerThreadController.h" #include "FileInfo.h" #include "DataBuffer.h" #include "../libchcore/FeedbackHandlerBase.h" @@ -250,7 +250,7 @@ TLocalFilesystem m_fsLocal; /// Thread controlling object - TWorkerThreadController m_workerThread; + chcore::TWorkerThreadController m_workerThread; /// Mutex for locking concurrent access to members of this class mutable boost::shared_mutex m_lock; Index: src/libchcore/ErrorCodes.h =================================================================== diff -u -N -r5fd6beaad9f1eccb664b997d151acb59961e4827 -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -41,6 +41,15 @@ // threading (1000+) eErr_MutexTimedOut = 1000, + eErr_CannotCreateEvent = 1001, + eErr_ThreadAlreadyStarted = 1002, + eErr_CannotResetEvent = 1003, + eErr_CannotCreateThread = 1004, + eErr_CannotChangeThreadPriority = 1005, + eErr_CannotResumeThread = 1006, + eErr_WaitingFailed = 1007, + eErr_CannotSuspendThread = 1008, + eErr_CannotSetEvent = 1009, // string errors (1500+) Index: src/libchcore/TCoreException.cpp =================================================================== diff -u -N -r5fd6beaad9f1eccb664b997d151acb59961e4827 -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/libchcore/TCoreException.cpp (.../TCoreException.cpp) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/libchcore/TCoreException.cpp (.../TCoreException.cpp) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -60,10 +60,49 @@ { } +// ============================================================================ +/// chcore::TCoreException::GetErrorInfo +/// @date 2011/07/18 +/// +/// @brief Retrieves formatted exception information. +/// @param[in] pszBuffer - buffer for formatted string +/// @param[in] stMaxBuffer - max size of buffer +// ============================================================================ void TCoreException::GetErrorInfo(wchar_t* pszBuffer, size_t stMaxBuffer) const { _snwprintf_s(pszBuffer, stMaxBuffer, _TRUNCATE, _T("Error code: %ld\r\nFile: %s\r\nFunction: %s\r\nLine no: %lu"), m_eErrorCode, m_pszFile, m_pszFunction, m_stLineNumber); pszBuffer[stMaxBuffer - 1] = _T('\0'); } +// ============================================================================ +/// chcore::TCoreWin32Exception::TCoreWin32Exception +/// @date 2011/07/18 +/// +/// @brief Constructs core win32 exception. +/// @param[in] eErrorCode - core error code +/// @param[in] dwWin32Exception - win32 error code +/// @param[in] pszFile -source file where the exception was thrown +/// @param[in] stLineNumber - source code line number where the exception was thrown +/// @param[in] pszFunction - function throwing the exception +// ============================================================================ +TCoreWin32Exception::TCoreWin32Exception(EGeneralErrors eErrorCode, DWORD dwWin32Exception, const tchar_t* pszFile, size_t stLineNumber, const tchar_t* pszFunction) : + TCoreException(eErrorCode, pszFile, stLineNumber, pszFunction), + m_dwWin32ErrorCode(dwWin32Exception) +{ +} + +// ============================================================================ +/// chcore::TCoreWin32Exception::GetErrorInfo +/// @date 2011/07/18 +/// +/// @brief Retrieves formatted exception information. +/// @param[in] pszBuffer - buffer for formatted string +/// @param[in] stMaxBuffer - max size of buffer +// ============================================================================ +void TCoreWin32Exception::GetErrorInfo(wchar_t* pszBuffer, size_t stMaxBuffer) const +{ + _snwprintf_s(pszBuffer, stMaxBuffer, _TRUNCATE, _T("Error code: %ld\r\nWin32 error code: %lu\r\nFile: %s\r\nFunction: %s\r\nLine no: %lu"), m_eErrorCode, m_dwWin32ErrorCode, m_pszFile, m_pszFunction, m_stLineNumber); + pszBuffer[stMaxBuffer - 1] = _T('\0'); +} + END_CHCORE_NAMESPACE Index: src/libchcore/TCoreException.h =================================================================== diff -u -N -r5fd6beaad9f1eccb664b997d151acb59961e4827 -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/libchcore/TCoreException.h (.../TCoreException.h) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/libchcore/TCoreException.h (.../TCoreException.h) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -27,9 +27,13 @@ // throws core exception object #define THROW_CORE_EXCEPTION(error_code)\ throw TCoreException(error_code, __FILEW__, __LINE__, __FUNCTIONW__) + #define THROW_CORE_EXCEPTION_STD(error_code, std_exception)\ throw TCoreException(error_code, std_exception, __FILEW__, __LINE__, __FUNCTIONW__) +#define THROW_CORE_EXCEPTION_WIN32(error_code, win32_error_code)\ + throw TCoreWin32Exception(error_code, win32_error_code, __FILEW__, __LINE__, __FUNCTIONW__) + class LIBCHCORE_API TCoreException : public virtual std::exception { public: @@ -47,7 +51,7 @@ void GetErrorInfo(wchar_t* pszBuffer, size_t stMaxBuffer) const; private: - TCoreException() {} + TCoreException(); protected: // what happened? @@ -59,6 +63,29 @@ size_t m_stLineNumber; }; +class LIBCHCORE_API TCoreWin32Exception : public TCoreException +{ +public: + TCoreWin32Exception(EGeneralErrors eErrorCode, DWORD dwWin32Exception, const tchar_t* pszFile, size_t stLineNumber, const tchar_t* pszFunction); + + DWORD GetWin32ErrorCode() const { return m_dwWin32ErrorCode; } + + void GetErrorInfo(wchar_t* pszBuffer, size_t stMaxBuffer) const; + +private: + TCoreWin32Exception(); + +protected: + // what happened? + EGeneralErrors m_eErrorCode; + DWORD m_dwWin32ErrorCode; + + // where it happened? + const wchar_t* m_pszFile; + const wchar_t* m_pszFunction; + size_t m_stLineNumber; +}; + END_CHCORE_NAMESPACE #endif Index: src/libchcore/TWorkerThreadController.cpp =================================================================== diff -u -N --- src/libchcore/TWorkerThreadController.cpp (revision 0) +++ src/libchcore/TWorkerThreadController.cpp (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -0,0 +1,213 @@ +// ============================================================================ +// Copyright (C) 2001-2010 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TWorkerThreadController.cpp +/// @date 2010/09/04 +/// @brief Contains implementation of class TWorkerThreadController. +// ============================================================================ +#include "stdafx.h" +#include "TWorkerThreadController.h" + +BEGIN_CHCORE_NAMESPACE + +TWorkerThreadController::TWorkerThreadController() : + m_hThread(NULL), + m_hKillThread(NULL) +{ + m_hKillThread = CreateEvent(NULL, TRUE, FALSE, NULL); + if(!m_hKillThread) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotCreateEvent, GetLastError()); +} + +TWorkerThreadController::~TWorkerThreadController() +{ + try + { + StopThread(); + CloseHandle(m_hKillThread); + } + catch(...) + { + } +} + +void TWorkerThreadController::StartThread(PTHREAD_START_ROUTINE pThreadFunction, PVOID pThreadParam, int iPriority) +{ + boost::upgrade_lock lock(m_lock); + + RemoveZombieData(lock); + + if(m_hThread) + THROW_CORE_EXCEPTION(eErr_ThreadAlreadyStarted); + + // just in case reset the kill event to avoid early death of the thread to be created + if(!::ResetEvent(m_hKillThread)) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResetEvent, GetLastError()); + + boost::upgrade_to_unique_lock lock_upgraded(lock); + + m_hThread = ::CreateThread(NULL, 0, pThreadFunction, pThreadParam, CREATE_SUSPENDED, NULL); + if(!m_hThread) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotCreateThread, GetLastError()); + + if(!::SetThreadPriority(m_hThread, iPriority)) + { + DWORD dwLastError = GetLastError(); + + CloseHandle(m_hThread); + m_hThread = NULL; + + THROW_CORE_EXCEPTION_WIN32(eErr_CannotChangeThreadPriority, dwLastError); + } + + if(::ResumeThread(m_hThread) == (DWORD)-1) + { + DWORD dwLastError = GetLastError(); + + CloseHandle(m_hThread); + m_hThread = NULL; + + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResumeThread, dwLastError); + } +} + +void TWorkerThreadController::SignalThreadToStop() +{ + boost::upgrade_lock lock(m_lock); + + SignalThreadToStop(lock); +} + +void TWorkerThreadController::WaitForThreadToExit() +{ + boost::upgrade_lock lock(m_lock); + + DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); + if(dwRes == WAIT_OBJECT_0) + { + if(!::ResetEvent(m_hKillThread)) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResetEvent, GetLastError()); + + boost::upgrade_to_unique_lock lock_upgraded(lock); + + CloseHandle(m_hThread); + m_hThread = NULL; + } + else + THROW_CORE_EXCEPTION_WIN32(eErr_WaitingFailed, GetLastError()); +} + +void TWorkerThreadController::StopThread() +{ + boost::upgrade_lock lock(m_lock); + + SignalThreadToStop(lock); + + WaitForThreadToExit(lock); +} + +void TWorkerThreadController::ChangePriority(int iPriority) +{ + boost::upgrade_lock lock(m_lock); + + RemoveZombieData(lock); + + if(!m_hThread) + return; + + if(m_hThread != NULL) + { + if(::SuspendThread(m_hThread) == (DWORD)-1) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotSuspendThread, GetLastError()); + + if(!::SetThreadPriority(m_hThread, iPriority)) + { + DWORD dwLastError = GetLastError(); + + // try to resume thread priority cannot be changed + DWORD dwResult = ::ResumeThread(m_hThread); + BOOST_ASSERT(dwResult != (DWORD)-1); + + THROW_CORE_EXCEPTION_WIN32(eErr_CannotChangeThreadPriority, dwLastError); + } + + if(::ResumeThread(m_hThread) == (DWORD)-1) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResumeThread, GetLastError()); + } +} + +bool TWorkerThreadController::KillRequested(DWORD dwWaitForSignal) +{ + // this method does not have any mutexes, because it should be only called from within the thread + // being controlled by this object. This implies that the thread is alive and running, + // this class must exist because it should not be possible for the thread to exist and be active + // when this object is out of scope, and so the m_hKillThread should be non-NULL, since it is being destroyed + // in destructor. + return (m_hKillThread && WaitForSingleObject(m_hKillThread, dwWaitForSignal) == WAIT_OBJECT_0); +} + +void TWorkerThreadController::RemoveZombieData(boost::upgrade_lock& rUpgradeLock) +{ + // if thread is already stopped, then there is nothing to do + if(!m_hThread) + return; + + // thread already stopped? + if(WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0) + { + if(!::ResetEvent(m_hKillThread)) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResetEvent, GetLastError()); + + boost::upgrade_to_unique_lock lock_upgraded(rUpgradeLock); + + CloseHandle(m_hThread); + m_hThread = NULL; + } +} + +void TWorkerThreadController::SignalThreadToStop(boost::upgrade_lock& rUpgradeLock) +{ + RemoveZombieData(rUpgradeLock); + if(!m_hThread) + return; + + if(!::SetEvent(m_hKillThread)) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotSetEvent, GetLastError()); +} + +void TWorkerThreadController::WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock) +{ + if(!m_hThread) + return; + + DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); + if(dwRes == WAIT_OBJECT_0) + { + if(!::ResetEvent(m_hKillThread)) + THROW_CORE_EXCEPTION_WIN32(eErr_CannotResetEvent, GetLastError()); + + boost::upgrade_to_unique_lock lock_upgraded(rUpgradeLock); + + CloseHandle(m_hThread); + m_hThread = NULL; + } + else + THROW_CORE_EXCEPTION_WIN32(eErr_WaitingFailed, GetLastError()); +} + +END_CHCORE_NAMESPACE Index: src/ch/TWorkerThreadController.cpp =================================================================== diff -u -N --- src/ch/TWorkerThreadController.cpp (revision b0d7cb2020371c35b5fbaab566b4dcc850fed460) +++ src/ch/TWorkerThreadController.cpp (revision 0) @@ -1,194 +0,0 @@ -// ============================================================================ -// Copyright (C) 2001-2010 by Jozef Starosczyk -// ixen@copyhandler.com -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License -// (version 2) as published by the Free Software Foundation; -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// ============================================================================ -/// @file TWorkerThreadController.cpp -/// @date 2010/09/04 -/// @brief Contains implementation of class TWorkerThreadController. -// ============================================================================ -#include "stdafx.h" -#include "TWorkerThreadController.h" - -TWorkerThreadController::TWorkerThreadController() : - m_hThread(NULL), - m_hKillThread(NULL) -{ - m_hKillThread = CreateEvent(NULL, TRUE, FALSE, NULL); - if(!m_hKillThread) - THROW(_T(""), 0, GetLastError(), 0); -} - -TWorkerThreadController::~TWorkerThreadController() -{ - StopThread(); - VERIFY(CloseHandle(m_hKillThread)); -} - -void TWorkerThreadController::StartThread(PTHREAD_START_ROUTINE pThreadFunction, PVOID pThreadParam, int iPriority) -{ - boost::upgrade_lock lock(m_lock); - - RemoveZombieData(lock); - - if(m_hThread) - THROW(_T("Thread already started"), 0, 0, 0); - - // just in case reset the kill event to avoid early death of the thread to be created - if(!::ResetEvent(m_hKillThread)) - THROW(_T("Cannot reset the kill event"), 0, GetLastError(), 0); - - boost::upgrade_to_unique_lock lock_upgraded(lock); - - m_hThread = ::CreateThread(NULL, 0, pThreadFunction, pThreadParam, CREATE_SUSPENDED, NULL); - if(!m_hThread) - THROW(_T("Cannot create thread"), 0, GetLastError(), 0); - - if(!::SetThreadPriority(m_hThread, iPriority)) - { - CloseHandle(m_hThread); - m_hThread = NULL; - - THROW(_T("Cannot set thread priority"), 0, GetLastError(), 0); - } - - if(::ResumeThread(m_hThread) == (DWORD)-1) - { - VERIFY(CloseHandle(m_hThread)); - m_hThread = NULL; - - THROW(_T("Cannot resume thread"), 0, GetLastError(), 0); - } -} - -void TWorkerThreadController::SignalThreadToStop() -{ - boost::upgrade_lock lock(m_lock); - - SignalThreadToStop(lock); -} - -void TWorkerThreadController::WaitForThreadToExit() -{ - boost::upgrade_lock lock(m_lock); - - DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); - if(dwRes == WAIT_OBJECT_0) - { - VERIFY(ResetEvent(m_hKillThread)); - - boost::upgrade_to_unique_lock lock_upgraded(lock); - VERIFY(CloseHandle(m_hThread)); - m_hThread = NULL; - return; - } - else - THROW(_T("Problem waiting for thread to finish"), 0, GetLastError(), 0); -} - -void TWorkerThreadController::StopThread() -{ - boost::upgrade_lock lock(m_lock); - - SignalThreadToStop(lock); - - WaitForThreadToExit(lock); -} - -void TWorkerThreadController::ChangePriority(int iPriority) -{ - boost::upgrade_lock lock(m_lock); - - RemoveZombieData(lock); - - if(!m_hThread) - return; - - if(m_hThread != NULL) - { - if(::SuspendThread(m_hThread) == (DWORD)-1) - THROW(_T("Cannot suspend thread"), 0, GetLastError(), 0); - - if(!::SetThreadPriority(m_hThread, iPriority)) - { - // resume thread if cannot change priority - VERIFY(::ResumeThread(m_hThread) != (DWORD)-1); - - THROW(_T("Cannot change the thread priority"), 0, GetLastError(), 0); - } - - if(::ResumeThread(m_hThread) == (DWORD)-1) - THROW(_T("Cannot resume thread"), 0, GetLastError(), 0); - } -} - -bool TWorkerThreadController::KillRequested(DWORD dwWaitForSignal) -{ - // this method does not have any mutexes, because it should be only called from within the thread - // being controlled by this object. This implies that the thread is alive and running, - // this class must exist because it should not be possible for the thread to exist and be active - // when this object is out of scope, and so the m_hKillThread should be non-NULL, since it is being destroyed - // in destructor. - return (m_hKillThread && WaitForSingleObject(m_hKillThread, dwWaitForSignal) == WAIT_OBJECT_0); -} - -void TWorkerThreadController::RemoveZombieData(boost::upgrade_lock& rUpgradeLock) -{ - // if thread is already stopped, then there is nothing to do - if(!m_hThread) - return; - - // thread already stopped? - if(WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0) - { - VERIFY(ResetEvent(m_hKillThread)); - - boost::upgrade_to_unique_lock lock_upgraded(rUpgradeLock); - - VERIFY(CloseHandle(m_hThread)); - - m_hThread = NULL; - } -} - -void TWorkerThreadController::SignalThreadToStop(boost::upgrade_lock& rUpgradeLock) -{ - RemoveZombieData(rUpgradeLock); - if(!m_hThread) - return; - - if(!SetEvent(m_hKillThread)) - THROW(_T("Cannot set the kill event for thread"), 0, GetLastError(), 0); -} - -void TWorkerThreadController::WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock) -{ - if(!m_hThread) - return; - - DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); - if(dwRes == WAIT_OBJECT_0) - { - VERIFY(ResetEvent(m_hKillThread)); - - boost::upgrade_to_unique_lock lock_upgraded(rUpgradeLock); - VERIFY(CloseHandle(m_hThread)); - m_hThread = NULL; - return; - } - else - THROW(_T("Problem waiting for thread to finish"), 0, GetLastError(), 0); -} Index: src/libchcore/TWorkerThreadController.h =================================================================== diff -u -N --- src/libchcore/TWorkerThreadController.h (revision 0) +++ src/libchcore/TWorkerThreadController.h (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -0,0 +1,71 @@ +// ============================================================================ +// Copyright (C) 2001-2009 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TWorkerThreadController.h +/// @date 2010/09/04 +/// @brief Contains class TWorkerThreadController. +// ============================================================================ +#ifndef __TWORKERTHREADCONTROLLER_H__ +#define __TWORKERTHREADCONTROLLER_H__ + +#include "libchcore.h" + +/////////////////////////////////////////////////////////////////////////// +// TWorkerThreadController + +BEGIN_CHCORE_NAMESPACE + +class LIBCHCORE_API TWorkerThreadController +{ +public: + TWorkerThreadController(); + ~TWorkerThreadController(); + + // methods to be used outside of the thread being controlled + void StartThread(PTHREAD_START_ROUTINE pThreadFunction, PVOID pThreadParam, int iPriority = THREAD_PRIORITY_NORMAL); + void SignalThreadToStop(); + void WaitForThreadToExit(); + + void StopThread(); + void ChangePriority(int iPriority); + + // methods to be used only inside the thread being controlled + bool KillRequested(DWORD dwWaitForSignal = 0); + +protected: + void RemoveZombieData(boost::upgrade_lock& rUpgradeLock); + + void SignalThreadToStop(boost::upgrade_lock& rUpgradeLock); + void WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock); + +private: + TWorkerThreadController(const TWorkerThreadController&); + TWorkerThreadController& operator=(const TWorkerThreadController&); + +private: + HANDLE m_hThread; + HANDLE m_hKillThread; +#pragma warning(push) +#pragma warning(disable: 4251) + boost::shared_mutex m_lock; +#pragma warning(pop) +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/ch/TWorkerThreadController.h =================================================================== diff -u -N --- src/ch/TWorkerThreadController.h (revision 44c811ed2e152c83d92aa7d0b41497a90a177209) +++ src/ch/TWorkerThreadController.h (revision 0) @@ -1,58 +0,0 @@ -// ============================================================================ -// Copyright (C) 2001-2009 by Jozef Starosczyk -// ixen@copyhandler.com -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License -// (version 2) as published by the Free Software Foundation; -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// ============================================================================ -/// @file TWorkerThreadController.h -/// @date 2010/09/04 -/// @brief Contains class TWorkerThreadController. -// ============================================================================ -#ifndef __TWORKERTHREADCONTROLLER_H__ -#define __TWORKERTHREADCONTROLLER_H__ - -/////////////////////////////////////////////////////////////////////////// -// TWorkerThreadController - -class TWorkerThreadController -{ -public: - TWorkerThreadController(); - ~TWorkerThreadController(); - - // methods to be used outside of the thread being controlled - void StartThread(PTHREAD_START_ROUTINE pThreadFunction, PVOID pThreadParam, int iPriority = THREAD_PRIORITY_NORMAL); - void SignalThreadToStop(); - void WaitForThreadToExit(); - - void StopThread(); - void ChangePriority(int iPriority); - - // methods to be used only inside the thread being controlled - bool KillRequested(DWORD dwWaitForSignal = 0); - -protected: - void RemoveZombieData(boost::upgrade_lock& rUpgradeLock); - - void SignalThreadToStop(boost::upgrade_lock& rUpgradeLock); - void WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock); - -private: - HANDLE m_hThread; - HANDLE m_hKillThread; - boost::shared_mutex m_lock; -}; - -#endif Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -N -r888524d8a33af49ee8e8ce83f98017323046f109 -rab32897e61cc637a1e28d9dc3f0489b8d16a429c --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 888524d8a33af49ee8e8ce83f98017323046f109) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision ab32897e61cc637a1e28d9dc3f0489b8d16a429c) @@ -531,6 +531,14 @@ RelativePath=".\TTaskOperationPlan.h" > + + + +