Index: src/ch/TWorkerThreadController.cpp =================================================================== diff -u --- src/ch/TWorkerThreadController.cpp (revision 0) +++ src/ch/TWorkerThreadController.cpp (revision 1402c0dd569ff5f381835966227f5b2836a755d6) @@ -0,0 +1,194 @@ +// ============================================================================ +// 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, FALSE, 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() +{ + // 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, 0) == 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/ch/TWorkerThreadController.h =================================================================== diff -u --- src/ch/TWorkerThreadController.h (revision 0) +++ src/ch/TWorkerThreadController.h (revision 1402c0dd569ff5f381835966227f5b2836a755d6) @@ -0,0 +1,58 @@ +// ============================================================================ +// 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(); + +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/ch/ch.vc90.vcproj =================================================================== diff -u -r9352ed0c4fe447a36bc728640c307be6d41455fd -r1402c0dd569ff5f381835966227f5b2836a755d6 --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 9352ed0c4fe447a36bc728640c307be6d41455fd) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 1402c0dd569ff5f381835966227f5b2836a755d6) @@ -1,7 +1,7 @@ + + + + SuspendThread(); - m_pThread->SetThreadPriority(nPriority); - m_pThread->ResumeThread(); - } - boost::unique_lock lock(m_lock); - m_nPriority = nPriority; - m_bSaved = false; + SetPriorityNL(nPriority); } void CTask::CalculateTotalSize() { unsigned long long ullTotalSize = 0; - boost::shared_lock lock(m_lock); + boost::shared_lock lock(m_lock); size_t nSize = m_files.GetSize(); for(size_t i = 0; i < nSize; i++) { @@ -628,32 +620,6 @@ m_localStats.SetProcessedSize(ullProcessedSize); } -// m_bKill -void CTask::SetKillFlag(bool bKill) -{ - boost::unique_lock lock(m_lock); - m_bKill=bKill; -} - -bool CTask::GetKillFlag() -{ - boost::shared_lock lock(m_lock); - return m_bKill; -} - -// m_bKilled -void CTask::SetKilledFlag(bool bKilled) -{ - boost::unique_lock lock(m_lock); - m_bKilled=bKilled; -} - -bool CTask::GetKilledFlag() -{ - boost::shared_lock lock(m_lock); - return m_bKilled; -} - // m_strUniqueName CString CTask::GetUniqueName() @@ -792,29 +758,17 @@ void CTask::KillThread() { - if(!GetKilledFlag()) // protection from recalling Cleanup - { - SetKillFlag(); - while(!GetKilledFlag()) - Sleep(10); - - // cleanup - CleanupAfterKill(); - } + m_workerThread.StopThread(); } void CTask::BeginProcessing() { - boost::unique_lock lock(m_lock); - if(m_pThread != NULL) - return; + boost::unique_lock lock(m_lock); - // create new thread - m_uiResumeInterval=0; // just in case - m_bSaved=false; // save - SetKillFlagNL(false); - SetKilledFlagNL(false); - m_pThread = AfxBeginThread(ThrdProc, this, GetPriorityNL()); + m_uiResumeInterval = 0; // just in case + m_bSaved = false; // save + + m_workerThread.StartThread(ThrdProc, this, m_nPriority); } void CTask::ResumeProcessing() @@ -1267,12 +1221,7 @@ void CTask::SetPriorityNL(int nPriority) { - if(m_pThread != NULL) - { - m_pThread->SuspendThread(); - m_pThread->SetThreadPriority(nPriority); - m_pThread->ResumeThread(); - } + m_workerThread.ChangePriority(nPriority); m_nPriority = nPriority; m_bSaved = false; @@ -1293,31 +1242,10 @@ m_localStats.SetTotalSize(ullTotalSize); } -void CTask::SetKillFlagNL(bool bKill) -{ - m_bKill = bKill; -} - -bool CTask::GetKillFlagNL() -{ - return m_bKill; -} - -void CTask::SetKilledFlagNL(bool bKilled) -{ - m_bKilled = bKilled; -} - -bool CTask::GetKilledFlagNL() -{ - return m_bKilled; -} - void CTask::CleanupAfterKillNL() { - m_pThread = NULL; UpdateTimeNL(); - m_lLastTime = -1; + m_lLastTime = -1; } void CTask::UpdateTimeNL() @@ -1479,7 +1407,7 @@ } // check for kill need - if(GetKillFlag()) + if(m_workerThread.KillRequested()) { // log m_log.logi(_T("Kill request while adding data to files array (RecurseDirectories)")); @@ -1546,7 +1474,7 @@ SetCurrentIndex(stIndex); // check for kill flag - if(GetKillFlag()) + if(m_workerThread.KillRequested()) { // log m_log.logi(_T("Kill request while deleting files (Delete Files)")); @@ -1911,7 +1839,7 @@ do { // kill flag checks - if(GetKillFlag()) + if(m_workerThread.KillRequested()) { // log fmt.SetFormat(_T("Kill request while main copying file %srcpath -> %dstpath")); @@ -2067,7 +1995,382 @@ throw; } } +/* +void CTask::CustomCopyFile2(CUSTOM_COPY_PARAMS* / *pData* /) +{ + // 1. DetermineStartupData: + bool bNoBuffering = false; // TODO: read from config file + + // additional variables + bool bRetry = false; + + // 2. Open source file + HANDLE hFile = INVALID_HANDLE_VALUE; + do + { + bRetry = false; + + hFile = CreateFile(_T("source_path"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + int iResponse = 0; // Ask user what to do + switch(iResponse) + { + case 0://eSkip: + return; + break; + case 1://eRetry: + bRetry = true; + break; + case 2://eCancel: + break; + case 3: //ePause: + break; + default: + throw; + } + } + } + while(bRetry); + + // 3. Open destination file - a more complex part + do + { + bRetry = false; + + hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + // creating new destination file have failed - either file exists or some other problem occurred + DWORD dwLastError = GetLastError(); + if(dwLastError == ERROR_FILE_EXISTS) + { + // destination file already exists - try to open existing file + do + { + hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + // opening existing destination file failed... + dwLastError = GetLastError(); + if(dwLastError == ERROR_ACCESS_DENIED) + { + // access to the file was denied - is it read only? + // ask user what to do (reset read-only attr, skip, pause, cancel, retry) + } + else + { + // some other error occurred when trying to open existing destination file + // ask user what todo + } + } + else + { + // existing destination file was successfully opened - gather information about it + // and ask user if he want to overwrite/append/skip/... + } + } + while(bRetry); + } + else + { + // there is other reason for file creation failure + } + } + } + while(bRetry); + + / * + + + + switch ERROR + { + * File already exists: + { + loop + { + ReOpenDestinationFile (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL) + if FAILED + { + switch ERROR + { + * Access denied = + { + GetFileAttributes + RESPONSE = Ask user + switch RESPONSE + { + * Skip / Retry / Cancel / Pause = + Standard + + ???????????????????????? + - problem with read only -> Delete ReadOnly attr + - standard options - skip/retry/cancel/pause + - rename option + - + ???????????????????????? + } + } + + * Other errors = + { + + } + } + else if SUCCEEDED + { + // append/overwrite? + // skip/cancel/pause (no retry?) + } + } + while RETRY + + RESPONSE = Ask user + switch RESPONSE + { + * Skip / Retry / Cancel / Pause = + Standard + + * Replace = + { + loop + { + ReOpenDestinationFile (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL) + if FAILED + { + + RESPONSE = Ask user + switch RESPONSE + { + * Skip / Retry / Cancel / Pause = + Standard + + + ???????????????????????? + - problem with read only -> Delete ReadOnly attr + - standard options - skip/retry/cancel/pause + - rename option + - + ???????????????????????? + } + } + } + while RETRY + + loop + { + SetEndOfFile at current file position (0) + if FAILED + { + * Skip = + exit proc -> continue with next src file + * Retry = + RETRY LOOP + * Cancel = + stop processing completely with cancelled status + * Pause = + stop processing completely with paused status + } + } + while RETRY + } + + * Append = + { + loop + { + ReOpen dst file (OPEN_EXISTING, NoBuffering ? NO_BUFFER : NORMAL) + if FAILED + { + RESPONSE = Ask user + switch RESPONSE + { + ???????????????????????? + } + } + } + while RETRY + + loop + { + SeekToEnd (possibly round down when NoBuffering) + if FAILED + { + * Skip = + exit proc -> continue with next src file + * Retry = + RETRY LOOP + * Cancel = + stop processing completely with cancelled status + * Pause = + stop processing completely with paused status + } + } + while RETRY + + loop + { + SeekToPosition for source file opened at pt 1 to position at which dst file has been set + if FAILED + { + * Skip = + exit proc -> continue with next src file + * Retry = + RETRY LOOP + * Cancel = + stop processing completely with cancelled status + * Pause = + stop processing completely with paused status + } + } + while RETRY + } + * Rename = + { + Store new filename + goto 2 + } + } + } + + * Other problems: + { + - Skip + - Retry + - Cancel + - Pause + - Rename = + Store new filename + goto 2 + } + } + } + } + while RETRY + } + while(bRetry); + + + 3. Copy contents of source file to destination file + - loop: + - Read xxx bytes from source file (take NoBuffer requirements into consideration) + - If bytes read are equal to those requested: + - write bytes to destination filename + - else + - + + + + + ////////////////////////////////////// + Standard options when asking user for feedback: + * Skip = + exit proc -> continue with next src file + * Retry = + RETRY LOOP + * Cancel = + stop processing completely with cancelled status + * Pause = + stop processing completely with paused status +* / +} +*/ +/* + +HANDLE CTask::OpenSourceFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /) +{ + bool bRetry = false; + HANDLE hFile = INVALID_HANDLE_VALUE; + do + { + bRetry = false; + + hFile = CreateFile(_T("source_path"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + int iResponse = 0; // Ask user what to do + switch(iResponse) + { + case 0://eSkip: + return; + break; + case 1://eRetry: + bRetry = true; + break; + case 2://eCancel: + break; + case 3: //ePause: + break; + default: + throw; + } + } + } + while(bRetry); + + return hFile; +} + +HANDLE CTask::CreateNewDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /) +{ + bool bRetry = false; + HANDLE hFile = INVALID_HANDLE_VALUE; + do + { + bRetry = false; + + hFile = CreateFile(_T("destination_path"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + // creating new destination file have failed - either file exists or some other problem occurred + DWORD dwLastError = GetLastError(); + if(dwLastError == ERROR_FILE_EXISTS) + { + // destination file already exists - try to open existing file + return OpenExistingDestinationFile(strPath, bNoBuffering); + } + else + { + // there is other reason for file creation failure + int iResponse = 0; // Ask user what to do + switch(iResponse) + { + case 0://eSkip: + return; + break; + case 1://eRetry: + bRetry = true; + break; + case 2://eCancel: + break; + case 3: //ePause: + break; + default: + throw; + } + } + } + while(bRetry); + + return hFile; +} + +HANDLE CTask::OpenExistingDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /) +{ + +} + +void CTask::SetEndOfFile(HANDLE hFile) +{ + +} + +void CTask::SeekToPosition(HANDLE hFile, unsigned long long ullPos) +{ + +} +*/ + // function processes files/folders void CTask::ProcessFiles() { @@ -2122,7 +2425,7 @@ for (size_t i = GetCurrentIndex(); i < stSize; i++) { // should we kill ? - if(GetKillFlag()) + if(m_workerThread.KillRequested()) { // log m_log.logi(_T("Kill request while processing file in ProcessFiles")); @@ -2291,7 +2594,7 @@ Sleep(50); // not to make it too hard for processor - if(GetKillFlag()) + if(m_workerThread.KillRequested()) { // log m_log.logi(_T("Kill request while waiting for begin permission (wait state)")); @@ -2300,7 +2603,7 @@ } } -UINT CTask::ThrdProc(LPVOID pParam) +DWORD CTask::ThrdProc(LPVOID pParam) { CTask* pTask = static_cast(pParam); @@ -2311,7 +2614,7 @@ pTask->m_log.init(strPath.c_str(), 262144, icpf::log_file::level_debug, false, false); - pTask->OnBeginOperation(); + pTask->OnBeginOperation(); // set thread boost HANDLE hThread=GetCurrentThread(); @@ -2422,11 +2725,10 @@ // play sound piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL); - pTask->OnEndOperation(); + pTask->OnEndOperation(); // we have been killed - the last operation pTask->CleanupAfterKill(); - pTask->SetKilledFlag(); } catch(CProcessingException* e) { @@ -2483,10 +2785,9 @@ pTask->SetContinueFlag(false); pTask->SetForceFlag(false); - pTask->OnEndOperation(); + pTask->OnEndOperation(); pTask->CleanupAfterKill(); - pTask->SetKilledFlag(); delete e; @@ -2526,6 +2827,11 @@ m_log.logi(fmt); } +void CTask::RequestStopThread() +{ + m_workerThread.SignalThreadToStop(); +} + //////////////////////////////////////////////////////////////////////////////// // CTaskArray members CTaskArray::CTaskArray() : @@ -2662,11 +2968,10 @@ CTaskPtr spTask = m_vTasks.at(stIndex); // delete only when the thread is finished - if((spTask->GetStatus(ST_STEP_MASK) == ST_FINISHED || spTask->GetStatus(ST_STEP_MASK) == ST_CANCELLED) - && spTask->GetKilledFlag()) + if((spTask->GetStatus(ST_STEP_MASK) == ST_FINISHED || spTask->GetStatus(ST_STEP_MASK) == ST_CANCELLED)) { - spTask->OnUnregisterTask(); - + spTask->OnUnregisterTask(); + vTasksToRemove.push_back(spTask); m_vTasks.erase(m_vTasks.begin() + stIndex); } @@ -2896,14 +3201,12 @@ // kill all unfinished tasks - send kill request BOOST_FOREACH(CTaskPtr& spTask, m_vTasks) { - spTask->SetKillFlagNL(); + spTask->RequestStopThread(); } // wait for finishing BOOST_FOREACH(CTaskPtr& spTask, m_vTasks) { - while(!spTask->GetKilledFlagNL()) - Sleep(10); - spTask->CleanupAfterKillNL(); + spTask->KillThread(); } } Index: src/ch/task.h =================================================================== diff -u -r4a3c74a38b00e7793d1e61107a824060e6c2ea95 -r1402c0dd569ff5f381835966227f5b2836a755d6 --- src/ch/task.h (.../task.h) (revision 4a3c74a38b00e7793d1e61107a824060e6c2ea95) +++ src/ch/task.h (.../task.h) (revision 1402c0dd569ff5f381835966227f5b2836a755d6) @@ -19,6 +19,7 @@ #ifndef __TASK_H__ #define __TASK_H__ +#include "TWorkerThreadController.h" #include "FileInfo.h" #include "DataBuffer.h" #include "../libchcore/FeedbackHandlerBase.h" @@ -340,14 +341,6 @@ void CalculateTotalSize(); - // m_bKill - void SetKillFlag(bool bKill = true); - bool GetKillFlag(); - - // m_bKilled - void SetKilledFlag(bool bKilled = true); - bool GetKilledFlag(); - void KillThread(); void CleanupAfterKill(); @@ -401,14 +394,29 @@ size_t GetSessionUniqueID() const { return m_stSessionUniqueID; } protected: - static UINT ThrdProc(LPVOID pParam); + static DWORD WINAPI ThrdProc(LPVOID pParam); void OnBeginOperation(); void OnEndOperation(); void CheckForWaitState(); void ProcessFiles(); void CustomCopyFile(CUSTOM_COPY_PARAMS* pData); + + // Playground +/* + void CustomCopyFile2(CUSTOM_COPY_PARAMS* / *pData* /); + + HANDLE OpenSourceFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /); + HANDLE CreateNewDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /); + HANDLE OpenExistingDestinationFile(const CString& strPath, bool bNoBuffering/ *, FeedbackSettings* /); + void SetEndOfFile(HANDLE hFile); + void SeekToPosition(HANDLE hFile, unsigned long long ullPos); +*/ + + + // End of playground + void DeleteFiles(); void RecurseDirectories(); static bool SetFileDirectoryTime(LPCTSTR lpszName, const CFileInfoPtr& spFileInfo); @@ -454,6 +462,8 @@ void SetContinueFlagNL(bool bFlag = true); bool GetContinueFlagNL(); + void RequestStopThread(); + private: icpf::log_file m_log; mutable boost::shared_mutex m_lock; // protection for this class @@ -487,12 +497,10 @@ // buffers BUFFERSIZES m_bsSizes; - CWinThread *m_pThread; + TWorkerThreadController m_workerThread; + int m_nPriority; - volatile bool m_bKill; - volatile bool m_bKilled; - // other stuff CString m_strUniqueName;