OSDN Git Service

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