OSDN Git Service

refactor
[winmerge-jp/winmerge-jp.git] / Src / DiffThread.cpp
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** 
3  * @file  DiffThread.cpp
4  *
5  * @brief Code for DiffThread class
6  */
7
8 #include "pch.h"
9 #include "DiffThread.h"
10 #include <cassert>
11 #include <climits>
12 #include <Poco/Thread.h>
13 #include <Poco/Semaphore.h>
14 #include "UnicodeString.h"
15 #include "CompareStats.h"
16 #include "IAbortable.h"
17 #include "Plugins.h"
18 #include "MergeAppCOMClass.h"
19 #include "DebugNew.h"
20
21 using Poco::Thread;
22 using Poco::Semaphore;
23
24 // Thread functions
25 static void DiffThreadCollect(void *lpParam);
26 static void DiffThreadCompare(void *lpParam);
27
28 /** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */
29 class DiffThreadAbortable : public IAbortable
30 {
31 // Implement DirScan's IAbortable
32 public:
33         virtual bool ShouldAbort() const override { return m_diffthread->ShouldAbort(); }
34
35 // All this object does is forward ShouldAbort calls to its containing CDiffThread
36
37         explicit DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
38         CDiffThread * m_diffthread;
39 };
40
41 /**
42  * @brief Default constructor.
43  */
44 CDiffThread::CDiffThread()
45 : m_pDiffContext(nullptr)
46 , m_bAborting(false)
47 , m_bPaused(false)
48 , m_pDiffParm(new DiffFuncStruct)
49 , m_pAbortgate(new DiffThreadAbortable(this))
50 {
51 }
52
53 /**
54  * @brief Destructor, release resources.
55  */
56 CDiffThread::~CDiffThread()
57 {
58         delete m_pDiffParm->pSemaphore;
59 }
60
61 /**
62  * @brief runtime interface for child thread, called on child thread
63  */
64 bool CDiffThread::ShouldAbort() const
65 {
66         while (m_bPaused && !m_bAborting)
67                 Poco::Thread::sleep(100);
68         return m_bAborting;
69 }
70
71 /**
72  * @brief Start and run directory compare thread.
73  * @return Success (1) or error for thread. Currently always 1.
74  */
75 unsigned CDiffThread::CompareDirectories()
76 {
77         assert(m_pDiffParm->nThreadState != THREAD_COMPARING && m_pDiffParm->nCollectThreadState != THREAD_COMPARING);
78
79         m_pDiffParm->context = m_pDiffContext;
80         m_pDiffParm->m_pAbortgate = m_pAbortgate.get();
81         m_bAborting = false;
82         m_bPaused = false;
83
84         m_pDiffParm->nThreadState = THREAD_COMPARING;
85         m_pDiffParm->nCollectThreadState = THREAD_COMPARING;
86
87         delete m_pDiffParm->pSemaphore;
88         m_pDiffParm->pSemaphore = new Semaphore(0, LONG_MAX);
89
90         m_pDiffParm->context->m_pCompareStats->SetCompareState(CompareStats::STATE_START);
91
92         m_threads[0].start(DiffThreadCollect, m_pDiffParm.get());
93         m_threads[1].start(DiffThreadCompare, m_pDiffParm.get());
94
95         return 1;
96 }
97
98 /**
99  * @brief Item collection thread function.
100  *
101  * This thread is responsible for finding and collecting all items to compare
102  * to the item list.
103  * @param [in] lpParam Pointer to parameter structure.
104  * @return Thread's return value.
105  */
106 static void DiffThreadCollect(void *pParam)
107 {
108         DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
109
110         // Stash abortable interface into context
111         myStruct->context->SetAbortable(myStruct->m_pAbortgate);
112
113         if (myStruct->m_fncCollect)
114                 myStruct->m_fncCollect(myStruct);
115
116         // Release Semaphore() once again to signal that collect phase is ready
117         myStruct->pSemaphore->set();
118
119         // Send message to UI to update
120         myStruct->nCollectThreadState = CDiffThread::THREAD_COMPLETED;
121         int event = CDiffThread::EVENT_COLLECT_COMPLETED;
122         myStruct->m_listeners.notify(myStruct, event);
123 };
124
125 /**
126  * @brief Folder compare thread function.
127  *
128  * Compares items in item list. After compare is ready
129  * sends message to UI so UI can update itself.
130  * @param [in] lpParam Pointer to parameter structure.
131  * @return Thread's return value.
132  */
133 static void DiffThreadCompare(void *pParam)
134 {
135         DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
136         CAssureScriptsForThread scriptsForRescan(new MergeAppCOMClass());
137
138         // Stash abortable interface into context
139         myStruct->context->SetAbortable(myStruct->m_pAbortgate);
140
141         myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
142
143         // Now do all pending file comparisons
144         myStruct->m_fncCompare(myStruct);
145
146         myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_IDLE);
147
148         // Send message to UI to update
149         myStruct->nThreadState = CDiffThread::THREAD_COMPLETED;
150         int event = CDiffThread::EVENT_COMPARE_COMPLETED;
151         myStruct->m_listeners.notify(myStruct, event);
152 }