From ce71a3d97dcfd3102e7974a9a7d8d4d2ad22e192 Mon Sep 17 00:00:00 2001 From: Perry Rapp Date: Sat, 25 Oct 2003 01:18:52 +0000 Subject: [PATCH] PATCH: [ 828633 ] Abort running scan --- Src/DiffThread.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++------------ Src/DiffThread.h | 31 +++++++++++----------- Src/DirDoc.cpp | 23 +++++++++++++++- Src/DirDoc.h | 2 ++ Src/DirScan.cpp | 14 ++++++++-- Src/DirScan.h | 12 ++++++++- Src/readme.txt | 5 ++++ 7 files changed, 129 insertions(+), 35 deletions(-) diff --git a/Src/DiffThread.cpp b/Src/DiffThread.cpp index 8ee956733..dd1d9f1c9 100644 --- a/Src/DiffThread.cpp +++ b/Src/DiffThread.cpp @@ -29,10 +29,45 @@ #include "DirScan.h" #include "Plugins.h" + /** - * @brief Static structure for sharing data with thread + * @brief Data sent to diff thread */ -static DiffFuncStruct diffParam; +struct DiffFuncStruct +{ + CString path1; + CString path2; + CDiffContext * context; + UINT msgUIUpdate; + UINT msgStatusUpdate; + HWND hWindow; + UINT nThreadState; + BOOL bRecursive; + DiffThreadAbortable * m_pAbortgate; + DiffFuncStruct() + : context(0) + , msgUIUpdate(0) + , msgStatusUpdate(0) + , hWindow(0) + , nThreadState(THREAD_NOTSTARTED) + , bRecursive(FALSE) + , m_pAbortgate(0) + {} +}; + + +/** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */ +class DiffThreadAbortable : public IAbortable +{ +// Implement DirScan's IAbortable +public: + virtual bool ShouldAbort() { return m_diffthread->ShouldAbort(); } + +// All this object does is forward ShouldAbort calls to its containing CDiffThread + + DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { } + CDiffThread * m_diffthread; +}; /** * @brief Default constructor @@ -41,11 +76,18 @@ CDiffThread::CDiffThread() { m_pDiffContext = NULL; m_thread = NULL; - diffParam.nThreadState = THREAD_NOTSTARTED; + m_pDiffParm = new DiffFuncStruct; + m_pAbortgate = new DiffThreadAbortable(this); + m_msgUpdateUI = 0; + m_msgUpdateStatus = 0; + m_hWnd = 0; + m_bAborting = FALSE; } CDiffThread::~CDiffThread() { + delete m_pDiffParm; + delete m_pAbortgate; } @@ -64,15 +106,18 @@ CDiffContext * CDiffThread::SetContext(CDiffContext * pCtx) */ UINT CDiffThread::CompareDirectories(CString dir1, CString dir2, BOOL bRecursive) { - diffParam.path1 = dir1; - diffParam.path2 = dir2; - diffParam.bRecursive = bRecursive; - diffParam.context = m_pDiffContext; - diffParam.msgUIUpdate = m_msgUpdateUI; - diffParam.hWindow = m_hWnd; - - diffParam.nThreadState = THREAD_COMPARING; - m_thread = AfxBeginThread(DiffThread, (LPVOID)&diffParam); + ASSERT(m_pDiffParm->nThreadState != THREAD_COMPARING); + + m_pDiffParm->path1 = dir1; + m_pDiffParm->path2 = dir2; + m_pDiffParm->bRecursive = bRecursive; + m_pDiffParm->context = m_pDiffContext; + m_pDiffParm->msgUIUpdate = m_msgUpdateUI; + m_pDiffParm->hWindow = m_hWnd; + m_pDiffParm->m_pAbortgate = m_pAbortgate; + + m_pDiffParm->nThreadState = THREAD_COMPARING; + m_thread = AfxBeginThread(DiffThread, m_pDiffParm); return 1; } @@ -96,9 +141,9 @@ void CDiffThread::SetMessageIDs(UINT updateMsg, UINT statusMsg) /** * @brief Returns thread's current state */ -UINT CDiffThread::GetThreadState() +UINT CDiffThread::GetThreadState() const { - return diffParam.nThreadState; + return m_pDiffParm->nThreadState; } /** @@ -120,10 +165,10 @@ UINT DiffThread(LPVOID lpParam) bool casesensitive = false; int depth = myStruct->bRecursive ? -1 : 0; CString subdir; // blank to start at roots specified in diff context - DirScan(subdir, myStruct->context, casesensitive, depth); + DirScan(subdir, myStruct->context, casesensitive, depth, myStruct->m_pAbortgate); // Send message to UI to update - diffParam.nThreadState = THREAD_COMPLETED; + myStruct->nThreadState = THREAD_COMPLETED; PostMessage(hWnd, msgID, NULL, NULL); return 1; } diff --git a/Src/DiffThread.h b/Src/DiffThread.h index 63498ecee..0a9e1b089 100644 --- a/Src/DiffThread.h +++ b/Src/DiffThread.h @@ -27,6 +27,9 @@ #include "diffcontext.h" +struct DiffFuncStruct; +class DiffThreadAbortable; + /** * @brief Thread's statuses */ @@ -37,20 +40,6 @@ enum THREAD_COMPLETED }; -/** - * @brief Data sent to diff thread - */ -struct DiffFuncStruct -{ - CString path1; - CString path2; - CDiffContext * context; - UINT msgUIUpdate; - UINT msgStatusUpdate; - HWND hWindow; - UINT nThreadState; - BOOL bRecursive; -}; /** * @brief Class for threaded directory compare @@ -59,20 +48,32 @@ struct DiffFuncStruct class CDiffThread { public: +// creation and use, called on main thread CDiffThread(); ~CDiffThread(); CDiffContext * SetContext(CDiffContext * pCtx); UINT CompareDirectories(CString dir1, CString dir2, BOOL bRecursive); void SetHwnd(HWND hWnd); void SetMessageIDs(UINT updateMsg, UINT statusMsg); - UINT GetThreadState(); + +// runtime interface for main thread, called on main thread + UINT GetThreadState() const; + void Abort() { m_bAborting = true; } + bool IsAborting() const { return m_bAborting; } + +// runtime interface for child thread, called on child thread + bool ShouldAbort() const { return m_bAborting; } + private: CDiffContext * m_pDiffContext; CWinThread * m_thread; + DiffFuncStruct * m_pDiffParm; + DiffThreadAbortable * m_pAbortgate; UINT m_msgUpdateUI; UINT m_msgUpdateStatus; HWND m_hWnd; + bool m_bAborting; }; UINT DiffThread(LPVOID lpParam); diff --git a/Src/DirDoc.cpp b/Src/DirDoc.cpp index 992179ef5..937939ad6 100644 --- a/Src/DirDoc.cpp +++ b/Src/DirDoc.cpp @@ -754,4 +754,25 @@ BOOL CDirDoc::SaveModified() return FALSE; return CDocument::SaveModified(); -} \ No newline at end of file +} + +/** + * @brief Send signal to thread to stop current scan + * + * @todo: Call this from somewhere in GUI, eg, button + */ +void CDirDoc::AbortCurrentScan() +{ + m_diffThread.Abort(); +} + +/** + * @brief Returns true if there is an active scan that hasn't been aborted. + * + * @todo: This is for Update command handler of menu item or toolbar button to cancel scan + */ +bool CDirDoc::IsCurrentScanAbortable() const +{ + return (m_diffThread.GetThreadState() == THREAD_COMPARING + && !m_diffThread.IsAborting()); +} diff --git a/Src/DirDoc.h b/Src/DirDoc.h index 293bb43e6..95f8d19ee 100644 --- a/Src/DirDoc.h +++ b/Src/DirDoc.h @@ -105,6 +105,8 @@ public: void SetDiffStatus(UINT diffcode, UINT mask, int idx); void SetDiffContext(CDiffContext *pCtxt); void UpdateHeaderPath(BOOL bLeft); + void AbortCurrentScan(); + bool IsCurrentScanAbortable() const; #ifdef _DEBUG virtual void AssertValid() const; diff --git a/Src/DirScan.cpp b/Src/DirScan.cpp index 6a41d901d..7dba5911a 100644 --- a/Src/DirScan.cpp +++ b/Src/DirScan.cpp @@ -51,7 +51,9 @@ typedef int (CString::*cmpmth)(LPCTSTR sz) const; // base directories to compare are in the CDiffContext // and this call is responsible for diff'ing just the subdir specified // (ie, if subdir is empty, this is the base call) -int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, int depth) +// return 1 normally, return -1 if aborting +int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, + int depth, IAbortable * piAbortable) { CString sLeftDir = pCtxt->m_strNormalizedLeft; CString sRightDir = pCtxt->m_strNormalizedRight; @@ -62,17 +64,22 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, in sRightDir += _T("\\") + subdir; subprefix = subdir + _T("\\"); } + cmpmth mthptr = (casesensitive ? &CString::Collate : &CString::CollateNoCase); fentryArray leftDirs, leftFiles, rightDirs, rightFiles; LoadAndSortFiles(sLeftDir, &leftDirs, &leftFiles, casesensitive); LoadAndSortFiles(sRightDir, &rightDirs, &rightFiles, casesensitive); + if (piAbortable && piAbortable->ShouldAbort()) return -1; + // Handle directories // i points to current directory in left list (leftDirs) // j points to current directory in right list (rightDirs) int i=0, j=0; while (1) { + if (piAbortable && piAbortable->ShouldAbort()) return -1; + // In debug mode, send current status to debug window if (iShouldAbort()) return -1; + // In debug mode, send current status to debug window if (i