OSDN Git Service

Leave the class name as CIniOptionsMgr, but rename the filename to IniOptionsMgr.*
[winmerge-jp/winmerge-jp.git] / Src / DiffThread.cpp
index 31236bb..552b19d 100644 (file)
-/////////////////////////////////////////////////////////////////////////////
-//    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
  */
-// RCS ID line follows -- this is updated by CVS
-// $Id$
 
-#include "stdafx.h"
-#include "diffcontext.h"
-#include "diffthread.h"
-#include "diff.h"
-#include "DirScan.h"
+#include "pch.h"
+#include "DiffThread.h"
+#include <cassert>
+#include <climits>
+#include <Poco/Thread.h>
+#include <Poco/Semaphore.h>
+#include "UnicodeString.h"
+#include "CompareStats.h"
+#include "IAbortable.h"
+#include "Plugins.h"
+#include "DebugNew.h"
 
-/**
- * @brief Static structure for sharing data with thread
- */
-static DiffFuncStruct diffParam;
+using Poco::Thread;
+using Poco::Semaphore;
 
-/**
- * @brief Default constructor
- */
-CDiffThread::CDiffThread()
-{
-       m_pDiffContext = NULL;
-       m_thread = NULL;
-       diffParam.nThreadState = THREAD_NOTSTARTED;
-}
+// Thread functions
+static void DiffThreadCollect(void *lpParam);
+static void DiffThreadCompare(void *lpParam);
 
-CDiffThread::~CDiffThread()
+/** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */
+class DiffThreadAbortable : public IAbortable
 {
+// Implement DirScan's IAbortable
+public:
+       virtual bool ShouldAbort() const override { return m_diffthread->ShouldAbort(); }
 
-}
+// All this object does is forward ShouldAbort calls to its containing CDiffThread
+
+       explicit DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
+       CDiffThread * m_diffthread;
+};
 
 /**
- * @brief Sets context pointer forwarded to thread
+ * @brief Default constructor.
  */
-CDiffContext * CDiffThread::SetContext(CDiffContext * pCtx)
+CDiffThread::CDiffThread()
+: m_pDiffContext(nullptr)
+, m_bAborting(false)
+, m_bPaused(false)
+, m_pDiffParm(new DiffFuncStruct)
+, m_pAbortgate(new DiffThreadAbortable(this))
 {
-       CDiffContext *pTempContext = m_pDiffContext;
-       m_pDiffContext = pCtx;
-       return pTempContext;
 }
 
 /**
- * @brief Start directory compare thread
+ * @brief Destructor, release resources.
  */
-UINT CDiffThread::CompareDirectories(CString dir1, CString dir2)
+CDiffThread::~CDiffThread()
 {
-       diffParam.path1 = dir1;
-       diffParam.path2 = dir2;
-       diffParam.context = m_pDiffContext;
-       diffParam.msgUIUpdate = m_msgUpdateUI;
-       diffParam.hWindow = m_hWnd;
-
-       diffParam.nThreadState = THREAD_COMPARING;
-       m_thread = AfxBeginThread(DiffThread, (LPVOID)&diffParam);
-       return 1;
+       delete m_pDiffParm->pSemaphore;
 }
 
 /**
- * @brief Set window receiving messages thread sends
+ * @brief runtime interface for child thread, called on child thread
  */
-void CDiffThread::SetHwnd(HWND hWnd)
+bool CDiffThread::ShouldAbort() const
 {
-       m_hWnd = hWnd;
+       while (m_bPaused && !m_bAborting)
+               Poco::Thread::sleep(100);
+       return m_bAborting;
 }
 
 /**
- * @brief Set message-id and -number for messages thread sends to window
+ * @brief Start and run directory compare thread.
+ * @return Success (1) or error for thread. Currently always 1.
  */
-void CDiffThread::SetMessageIDs(UINT updateMsg, UINT statusMsg)
+unsigned CDiffThread::CompareDirectories()
 {
-       m_msgUpdateUI = updateMsg;
-       m_msgUpdateStatus = statusMsg;
+       assert(m_pDiffParm->nThreadState != THREAD_COMPARING);
+
+       m_pDiffParm->context = m_pDiffContext;
+       m_pDiffParm->m_pAbortgate = m_pAbortgate.get();
+       m_bAborting = false;
+       m_bPaused = false;
+
+       m_pDiffParm->nThreadState = THREAD_COMPARING;
+
+       delete m_pDiffParm->pSemaphore;
+       m_pDiffParm->pSemaphore = new Semaphore(0, LONG_MAX);
+
+       m_pDiffParm->context->m_pCompareStats->SetCompareState(CompareStats::STATE_START);
+
+       m_threads[0].start(DiffThreadCollect, m_pDiffParm.get());
+       m_threads[1].start(DiffThreadCompare, m_pDiffParm.get());
+
+       return 1;
 }
 
 /**
- * @brief Returns thread's current state
+ * @brief Item collection thread function.
+ *
+ * This thread is responsible for finding and collecting all items to compare
+ * to the item list.
+ * @param [in] lpParam Pointer to parameter structure.
+ * @return Thread's return value.
  */
-UINT CDiffThread::GetThreadState()
+static void DiffThreadCollect(void *pParam)
 {
-       return diffParam.nThreadState;
-}
+       DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
+
+       // Stash abortable interface into context
+       myStruct->context->SetAbortable(myStruct->m_pAbortgate);
+
+       if (myStruct->m_fncCollect)
+               myStruct->m_fncCollect(myStruct);
+
+       // Release Semaphore() once again to signal that collect phase is ready
+       myStruct->pSemaphore->set();
+
+       // Send message to UI to update
+       int event = CDiffThread::EVENT_COLLECT_COMPLETED;
+       myStruct->m_listeners.notify(myStruct, event);
+};
 
 /**
- * @brief Directory compare thread function
- * Calls diffutils's compare_files() and after compare is ready
+ * @brief Folder compare thread function.
+ *
+ * Compares items in item list. After compare is ready
  * sends message to UI so UI can update itself.
+ * @param [in] lpParam Pointer to parameter structure.
+ * @return Thread's return value.
  */
-UINT DiffThread(LPVOID lpParam)
+static void DiffThreadCompare(void *pParam)
 {
-       DiffFuncStruct *myStruct = (DiffFuncStruct *) lpParam;
-       HWND hWnd = myStruct->hWindow;
-       UINT msgID = myStruct->msgUIUpdate;
-
-       bool casesensitive = false;
-       int depth = -1;
-       CString subdir; // blank to start at roots specified in diff context
-       DirScan(subdir, myStruct->context, casesensitive, depth);
-       
+       DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
+       CAssureScriptsForThread scriptsForRescan;
+
+       // Stash abortable interface into context
+       myStruct->context->SetAbortable(myStruct->m_pAbortgate);
+
+       myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
+
+       // Now do all pending file comparisons
+       myStruct->m_fncCompare(myStruct);
+
+       myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_IDLE);
+
        // Send message to UI to update
-       diffParam.nThreadState = THREAD_COMPLETED;
-       SendMessage(hWnd, msgID, NULL, NULL);
-       return 1;
+       myStruct->nThreadState = CDiffThread::THREAD_COMPLETED;
+       int event = CDiffThread::EVENT_COMPARE_COMPLETED;
+       myStruct->m_listeners.notify(myStruct, event);
 }