OSDN Git Service

PATCH: [ 828633 ] Abort running scan
authorPerry Rapp <elsapo@users.sourceforge.net>
Sat, 25 Oct 2003 01:18:52 +0000 (01:18 +0000)
committerPerry Rapp <elsapo@users.sourceforge.net>
Sat, 25 Oct 2003 01:18:52 +0000 (01:18 +0000)
Src/DiffThread.cpp
Src/DiffThread.h
Src/DirDoc.cpp
Src/DirDoc.h
Src/DirScan.cpp
Src/DirScan.h
Src/readme.txt

index 8ee9567..dd1d9f1 100644 (file)
 #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;
 }
index 63498ec..0a9e1b0 100644 (file)
@@ -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);
index 992179e..937939a 100644 (file)
@@ -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, <escape> 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());
+}
index 293bb43..95f8d19 100644 (file)
@@ -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;
index 6a41d90..7dba591 100644 (file)
@@ -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 (i<leftDirs.GetSize())
                        TRACE(_T("Candidate left: leftDirs[i]=%s\n"), leftDirs[i]);
@@ -118,7 +125,8 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, in
                        }
                        else
                        {
-                               DirScan(newsub, pCtxt, casesensitive, depth-1); 
+                               if (DirScan(newsub, pCtxt, casesensitive, depth-1, piAbortable) == -1)
+                                       return -1;
                        }
                        ++i;
                        ++j;
@@ -132,6 +140,8 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, in
        i=0, j=0;
        while (1)
        {
+               if (piAbortable && piAbortable->ShouldAbort()) return -1;
+
                // In debug mode, send current status to debug window
                if (i<leftFiles.GetSize())
                        TRACE(_T("Candidate left: leftFiles[i]=%s\n"), leftFiles[i]);
index 2d42606..f9ef58a 100644 (file)
@@ -2,7 +2,17 @@
 #define DirScan_h_included
 
 class CDiffContext;
-int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive, int depth=-1);
+
+/** @brief callback to check if dirscan needs to abort */
+class IAbortable
+{
+public:
+       virtual bool ShouldAbort() = 0;
+};
+
+int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
+       int depth, IAbortable * piAbortable);
+
 
 #endif // DirScan_h_included
 
index cc40abb..9572cfd 100644 (file)
@@ -1,3 +1,8 @@
+2003-10-25 Perry
+ PATCH: [ 828633 ] Abort running scan
+  WinMerge: DiffThread.cpp DiffThread.h DirDoc.cpp DirDoc.h
+   DirScan.cpp DirScan.h
+
 2003-10-24 Perry
  PATCH: [ 814832 ] Timing traces for loading file
   WinMerge: MergeDoc.cpp