OSDN Git Service

Leave the class name as CIniOptionsMgr, but rename the filename to IniOptionsMgr.*
[winmerge-jp/winmerge-jp.git] / Src / DiffThread.cpp
index fcc0d8b..552b19d 100644 (file)
@@ -1,60 +1,39 @@
-/////////////////////////////////////////////////////////////////////////////
-//    License (GPLv2+):
-//    This program is free software; you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation; either version 2 of the License, or (at
-//    your option) any later version.
-//    
-//    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 General Public License
-//    along with this program; if not, write to the Free Software
-//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-/////////////////////////////////////////////////////////////////////////////
+// SPDX-License-Identifier: GPL-2.0-or-later
 /** 
  * @file  DiffThread.cpp
  *
  * @brief Code for DiffThread class
  */
-// ID line follows -- this is updated by SVN
-// $Id: DiffThread.cpp 6910 2009-07-12 09:06:54Z kimmov $
 
-#include "stdafx.h"
+#include "pch.h"
+#include "DiffThread.h"
+#include <cassert>
+#include <climits>
+#include <Poco/Thread.h>
+#include <Poco/Semaphore.h>
 #include "UnicodeString.h"
-#include "diffcontext.h"
-#include "diffthread.h"
-#include "DirScan.h"
-#include "Plugins.h"
-#include "DiffItemList.h"
-#include "PathContext.h"
 #include "CompareStats.h"
 #include "IAbortable.h"
+#include "Plugins.h"
+#include "DebugNew.h"
 
-/**
- * @brief Force compare to be single-threaded.
- * Set this to true in order to single step through entire compare process all
- * in a single thread. Either edit this line, or breakpoint & change it in
- * CompareDirectories() below.
- *
- * If you are going to debug compare procedure, you most probably need to set
- * this to true. As Visual Studio seems to have real problems with debugging
- * these threads otherwise.
- */
-static bool bSinglethreaded = false;
+using Poco::Thread;
+using Poco::Semaphore;
+
+// Thread functions
+static void DiffThreadCollect(void *lpParam);
+static void DiffThreadCompare(void *lpParam);
 
 /** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */
 class DiffThreadAbortable : public IAbortable
 {
 // Implement DirScan's IAbortable
 public:
-       virtual bool ShouldAbort() const { return m_diffthread->ShouldAbort(); }
+       virtual bool ShouldAbort() const override { return m_diffthread->ShouldAbort(); }
 
 // All this object does is forward ShouldAbort calls to its containing CDiffThread
 
-       DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
+       explicit DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
        CDiffThread * m_diffthread;
 };
 
@@ -62,14 +41,12 @@ public:
  * @brief Default constructor.
  */
 CDiffThread::CDiffThread()
-: m_pDiffContext(NULL)
-, m_msgUpdateUI(0)
-, m_hWnd(0)
-, m_bAborting(FALSE)
+: m_pDiffContext(nullptr)
+, m_bAborting(false)
+, m_bPaused(false)
+, m_pDiffParm(new DiffFuncStruct)
+, m_pAbortgate(new DiffThreadAbortable(this))
 {
-       ZeroMemory(&m_threads[0], sizeof(m_threads));
-       m_pDiffParm = new DiffFuncStruct;
-       m_pAbortgate = new DiffThreadAbortable(this);
 }
 
 /**
@@ -77,18 +54,7 @@ CDiffThread::CDiffThread()
  */
 CDiffThread::~CDiffThread()
 {
-       CloseHandle(m_pDiffParm->hSemaphore);
-       delete m_pDiffParm;
-       delete m_pAbortgate;
-}
-
-/**
- * @brief Sets context pointer forwarded to thread.
- * @param [in] pCtx Pointer to compare context.
- */
-void CDiffThread::SetContext(CDiffContext * pCtx)
-{
-       m_pDiffContext = pCtx;
+       delete m_pDiffParm->pSemaphore;
 }
 
 /**
@@ -96,93 +62,38 @@ void CDiffThread::SetContext(CDiffContext * pCtx)
  */
 bool CDiffThread::ShouldAbort() const
 {
-       if (bSinglethreaded)
-       {
-               MSG msg;
-               while (::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
-               {
-                       AfxGetApp()->PumpMessage();
-               }
-       }
+       while (m_bPaused && !m_bAborting)
+               Poco::Thread::sleep(100);
        return m_bAborting;
 }
 
 /**
  * @brief Start and run directory compare thread.
- * @param [in] dir1 First directory to compare.
- * @param [in] dir2 Second directory to compare.
  * @return Success (1) or error for thread. Currently always 1.
  */
-UINT CDiffThread::CompareDirectories(const String & dir1,
-               const String & dir2)
+unsigned CDiffThread::CompareDirectories()
 {
-       ASSERT(m_pDiffParm->nThreadState != THREAD_COMPARING);
+       assert(m_pDiffParm->nThreadState != THREAD_COMPARING);
 
        m_pDiffParm->context = m_pDiffContext;
-       m_pDiffParm->msgUIUpdate = m_msgUpdateUI;
-       m_pDiffParm->hWindow = m_hWnd;
-       m_pDiffParm->m_pAbortgate = m_pAbortgate;
-       m_pDiffParm->bOnlyRequested = m_bOnlyRequested;
-       m_bAborting = FALSE;
+       m_pDiffParm->m_pAbortgate = m_pAbortgate.get();
+       m_bAborting = false;
+       m_bPaused = false;
 
        m_pDiffParm->nThreadState = THREAD_COMPARING;
 
-       m_pDiffParm->hSemaphore = CreateSemaphore(0, 0, LONG_MAX, 0);
+       delete m_pDiffParm->pSemaphore;
+       m_pDiffParm->pSemaphore = new Semaphore(0, LONG_MAX);
 
        m_pDiffParm->context->m_pCompareStats->SetCompareState(CompareStats::STATE_START);
 
-       if (bSinglethreaded)
-       {
-               if (m_bOnlyRequested == FALSE)
-                       DiffThreadCollect(m_pDiffParm);
-               DiffThreadCompare(m_pDiffParm);
-       }
-       else
-       {
-               if (m_bOnlyRequested == FALSE)
-                       m_threads[0] = AfxBeginThread(DiffThreadCollect, m_pDiffParm);
-               m_threads[1] = AfxBeginThread(DiffThreadCompare, m_pDiffParm);
-       }
+       m_threads[0].start(DiffThreadCollect, m_pDiffParm.get());
+       m_threads[1].start(DiffThreadCompare, m_pDiffParm.get());
 
        return 1;
 }
 
 /**
- * @brief Set window receiving messages thread sends.
- * @param [in] hWnd Hand to window to receive messages.
- */
-void CDiffThread::SetHwnd(HWND hWnd)
-{
-       m_hWnd = hWnd;
-}
-
-/**
- * @brief Set message-id for update message.
- * @param [in] updateMsg Message-id for update message.
- */
-void CDiffThread::SetMessageIDs(UINT updateMsg)
-{
-       m_msgUpdateUI = updateMsg;
-}
-
-/**
- * @brief Selects to compare all or only selected items.
- * @param [in] bSelected If TRUE only selected items are compared.
- */
-void CDiffThread::SetCompareSelected(bool bSelected /*=FALSE*/)
-{
-       m_bOnlyRequested = bSelected;
-}
-
-/**
- * @brief Returns thread's current state
- */
-UINT CDiffThread::GetThreadState() const
-{
-       return m_pDiffParm->nThreadState;
-}
-
-/**
  * @brief Item collection thread function.
  *
  * This thread is responsible for finding and collecting all items to compare
@@ -190,50 +101,23 @@ UINT CDiffThread::GetThreadState() const
  * @param [in] lpParam Pointer to parameter structure.
  * @return Thread's return value.
  */
-UINT DiffThreadCollect(LPVOID lpParam)
+static void DiffThreadCollect(void *pParam)
 {
-       PathContext paths;
-       DiffFuncStruct *myStruct = (DiffFuncStruct *) lpParam;
-
-       ASSERT(myStruct->bOnlyRequested == FALSE);
+       DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
 
        // Stash abortable interface into context
        myStruct->context->SetAbortable(myStruct->m_pAbortgate);
 
-       // keep the scripts alive during the Rescan
-       // when we exit the thread, we delete this and release the scripts
-       CAssureScriptsForThread scriptsForRescan;
-
-       bool casesensitive = false;
-       int depth = myStruct->context->m_bRecursive ? -1 : 0;
+       if (myStruct->m_fncCollect)
+               myStruct->m_fncCollect(myStruct);
 
-       paths = myStruct->context->GetNormalizedPaths();
-
-       LPCTSTR subdir[3] = {_T(""), _T(""), _T("")}; // blank to start at roots specified in diff context
-#ifdef _DEBUG
-       _CrtMemState memStateBefore;
-       _CrtMemState memStateAfter;
-       _CrtMemState memStateDiff;
-       _CrtMemCheckpoint(&memStateBefore);
-#endif
-
-       // Build results list (except delaying file comparisons until below)
-       DirScan_GetItems(paths, subdir, myStruct,
-                       casesensitive, depth, NULL, myStruct->context->m_bWalkUniques);
-
-#ifdef _DEBUG
-       _CrtMemCheckpoint(&memStateAfter);
-       _CrtMemDifference(&memStateDiff, &memStateBefore, &memStateAfter);
-       _CrtMemDumpStatistics(&memStateDiff);
-#endif
-
-       // ReleaseSemaphore() once again to signal that collect phase is ready
-       ReleaseSemaphore(myStruct->hSemaphore, 1, 0);
+       // Release Semaphore() once again to signal that collect phase is ready
+       myStruct->pSemaphore->set();
 
        // Send message to UI to update
-       PostMessage(myStruct->hWindow, myStruct->msgUIUpdate, 2, myStruct->bOnlyRequested);
-       return 1;
-}
+       int event = CDiffThread::EVENT_COLLECT_COMPLETED;
+       myStruct->m_listeners.notify(myStruct, event);
+};
 
 /**
  * @brief Folder compare thread function.
@@ -243,30 +127,23 @@ UINT DiffThreadCollect(LPVOID lpParam)
  * @param [in] lpParam Pointer to parameter structure.
  * @return Thread's return value.
  */
-UINT DiffThreadCompare(LPVOID lpParam)
+static void DiffThreadCompare(void *pParam)
 {
-       DiffFuncStruct *myStruct = (DiffFuncStruct *) lpParam;
+       DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
+       CAssureScriptsForThread scriptsForRescan;
 
        // Stash abortable interface into context
        myStruct->context->SetAbortable(myStruct->m_pAbortgate);
 
-       // keep the scripts alive during the Rescan
-       // when we exit the thread, we delete this and release the scripts
-       CAssureScriptsForThread scriptsForRescan;
-
        myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
 
        // Now do all pending file comparisons
-       if (myStruct->bOnlyRequested)
-               DirScan_CompareRequestedItems(myStruct, NULL);
-       else
-               DirScan_CompareItems(myStruct, NULL);
+       myStruct->m_fncCompare(myStruct);
 
        myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_IDLE);
 
        // Send message to UI to update
        myStruct->nThreadState = CDiffThread::THREAD_COMPLETED;
-       // msgID=MSG_UI_UPDATE=1025 (2005-11-29, Perry)
-       PostMessage(myStruct->hWindow, myStruct->msgUIUpdate, NULL, myStruct->bOnlyRequested);
-       return 1;
+       int event = CDiffThread::EVENT_COMPARE_COMPLETED;
+       myStruct->m_listeners.notify(myStruct, event);
 }