forked from WinMerge/winmerge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDiffThread.h
154 lines (139 loc) · 4.32 KB
/
DiffThread.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// SPDX-License-Identifier: GPL-2.0-or-later
/**
* @file DiffThread.h
*
* @brief Declaration file for CDiffThread
*/
#pragma once
#include <memory>
#include <functional>
#define POCO_NO_UNWINDOWS 1
#include <Poco/Thread.h>
#include <Poco/BasicEvent.h>
#include <Poco/Delegate.h>
#include "DiffContext.h"
namespace Poco
{
class Semaphore;
}
class DiffThreadAbortable;
/**
* @brief Structure used in sending data to the threads.
* As thread functions have only one parameter we must pack all
* the data we need inside structure.
*/
struct DiffFuncStruct
{
CDiffContext * context; /**< Compare context. */
Poco::BasicEvent<int> m_listeners; /**< Event listeners */
int nThreadState; /**< Thread state. */
int nCollectThreadState; /**< Collect thread state. */
DiffThreadAbortable * m_pAbortgate; /**< Interface for aborting compare. */
Poco::Semaphore *pSemaphore; /**< Semaphore for synchronizing threads. */
std::function<void (DiffFuncStruct*)> m_fncCollect;
std::function<void (DiffFuncStruct*)> m_fncCompare;
bool bMarkedRescan; /**< Is the rescan due to "Refresh Selected"? */
DiffFuncStruct()
: context(nullptr)
, nThreadState(0/*CDiffThread::THREAD_NOTSTARTED*/)
, nCollectThreadState(0/*CDiffThread::THREAD_NOTSTARTED*/)
, m_pAbortgate(nullptr)
, pSemaphore(nullptr)
, bMarkedRescan(false)
{}
};
/**
* @brief Class for threaded folder compare.
* This class implements folder compare in two phases and in two threads:
* - first thread collects items to compare to compare-time list
* (m_diffList).
* - second threads compares items in the list.
*/
class CDiffThread
{
public:
/** @brief Thread's states. */
enum ThreadState
{
THREAD_NOTSTARTED = 0, /**< Thread not started, idle. */
THREAD_COMPARING, /**< Thread running (comparing). */
THREAD_COMPLETED, /**< Thread has completed its task. */
};
enum ThreadEvent
{
EVENT_COLLECT_COMPLETED = 2,
EVENT_COMPARE_PROGRESSED = 1,
EVENT_COMPARE_COMPLETED = 0,
};
// creation and use, called on main thread
CDiffThread();
~CDiffThread();
void SetContext(CDiffContext * pCtx);
unsigned CompareDirectories();
template<class T>
void AddListener(T *pObj, void (T::*pMethod)(int& state)) {
m_pDiffParm->m_listeners += Poco::delegate(pObj, pMethod);
}
template<class T>
void RemoveListener(T *pObj, void (T::*pMethod)(int& state)) {
m_pDiffParm->m_listeners -= Poco::delegate(pObj, pMethod);
}
void SetCollectFunction(std::function<void(DiffFuncStruct*)> func) { m_pDiffParm->m_fncCollect = func; }
void SetCompareFunction(std::function<void(DiffFuncStruct*)> func) { m_pDiffParm->m_fncCompare = func; }
void SetMarkedRescan(bool bMarkedRescan);
bool IsMarkedRescan() const;
// runtime interface for main thread, called on main thread
unsigned GetThreadState() const;
unsigned GetCollectThreadState() const;
void Abort() { m_bAborting = true; }
bool IsAborting() const { return m_bAborting; }
void Pause() { m_bPaused = true; }
void Continue() { m_bPaused = false; }
bool IsPaused() const { return m_bPaused; }
// runtime interface for child thread, called on child thread
bool ShouldAbort() const;
private:
CDiffContext * m_pDiffContext; /**< Compare context storing results. */
Poco::Thread m_threads[2]; /**< Compare threads. */
std::unique_ptr<DiffFuncStruct> m_pDiffParm; /**< Structure for sending data to threads. */
std::unique_ptr<DiffThreadAbortable> m_pAbortgate;
bool m_bAborting; /**< Is compare aborting? */
bool m_bPaused; /**< Is compare paused? */
};
/**
* @brief Sets context pointer forwarded to thread.
* @param [in] pCtx Pointer to compare context.
*/
inline void CDiffThread::SetContext(CDiffContext * pCtx)
{
m_pDiffContext = pCtx;
}
/**
* @brief Returns thread's current state
*/
inline unsigned CDiffThread::GetThreadState() const
{
return m_pDiffParm->nThreadState;
}
/**
* @brief Returns collect thread's current state
*/
inline unsigned CDiffThread::GetCollectThreadState() const
{
return m_pDiffParm->nCollectThreadState;
}
/**
* @brief Sets whether the rescan is due to "Refresh Selected"
* @param [in] bMarkedRescan Is the rescan due to "Refresh Selected"?
*/
inline void CDiffThread::SetMarkedRescan(bool bMarkedRescan)
{
m_pDiffParm->bMarkedRescan = bMarkedRescan;
}
/**
* @brief Returns whether the rescan is due to "Refresh Selected"
*/
inline bool CDiffThread::IsMarkedRescan() const
{
return m_pDiffParm->bMarkedRescan;
}