1 /////////////////////////////////////////////////////////////////////////////
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or (at
6 // your option) any later version.
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 /////////////////////////////////////////////////////////////////////////////
18 * @file DiffThread.cpp
20 * @brief Code for DiffThread class
23 #include "DiffThread.h"
26 #include <Poco/Thread.h>
27 #include <Poco/Semaphore.h>
28 #include "UnicodeString.h"
29 #include "DiffContext.h"
31 #include "DiffItemList.h"
32 #include "PathContext.h"
33 #include "CompareStats.h"
34 #include "IAbortable.h"
37 using Poco::Semaphore;
40 static void DiffThreadCollect(void *lpParam);
41 static void DiffThreadCompare(void *lpParam);
43 /** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */
44 class DiffThreadAbortable : public IAbortable
46 // Implement DirScan's IAbortable
48 virtual bool ShouldAbort() const { return m_diffthread->ShouldAbort(); }
50 // All this object does is forward ShouldAbort calls to its containing CDiffThread
52 explicit DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
53 CDiffThread * m_diffthread;
57 * @brief Default constructor.
59 CDiffThread::CDiffThread()
60 : m_pDiffContext(NULL)
63 , m_pDiffParm(new DiffFuncStruct)
65 m_pAbortgate.reset(new DiffThreadAbortable(this));
69 * @brief Destructor, release resources.
71 CDiffThread::~CDiffThread()
73 delete m_pDiffParm->pSemaphore;
77 * @brief Sets context pointer forwarded to thread.
78 * @param [in] pCtx Pointer to compare context.
80 void CDiffThread::SetContext(CDiffContext * pCtx)
82 m_pDiffContext = pCtx;
86 * @brief runtime interface for child thread, called on child thread
88 bool CDiffThread::ShouldAbort() const
90 while (m_bPaused && !m_bAborting)
91 Poco::Thread::sleep(100);
96 * @brief Start and run directory compare thread.
97 * @return Success (1) or error for thread. Currently always 1.
99 unsigned CDiffThread::CompareDirectories()
101 assert(m_pDiffParm->nThreadState != THREAD_COMPARING);
103 m_pDiffParm->context = m_pDiffContext;
104 m_pDiffParm->m_pAbortgate = m_pAbortgate.get();
105 m_pDiffParm->bOnlyRequested = m_bOnlyRequested;
109 m_pDiffParm->nThreadState = THREAD_COMPARING;
111 delete m_pDiffParm->pSemaphore;
112 m_pDiffParm->pSemaphore = new Semaphore(0, LONG_MAX);
114 m_pDiffParm->context->m_pCompareStats->SetCompareState(CompareStats::STATE_START);
116 if (m_bOnlyRequested == false)
117 m_threads[0].start(DiffThreadCollect, m_pDiffParm.get());
120 int nItems = DirScan_UpdateMarkedItems(m_pDiffParm.get(), 0);
121 // Send message to UI to update
122 int event = CDiffThread::EVENT_COLLECT_COMPLETED;
123 m_pDiffParm->m_listeners.notify(m_pDiffParm.get(), event);
124 m_pDiffParm->context->m_pCompareStats->IncreaseTotalItems(nItems - m_pDiffParm->context->m_pCompareStats->GetTotalItems());
126 m_threads[1].start(DiffThreadCompare, m_pDiffParm.get());
132 * @brief Selects to compare all or only selected items.
133 * @param [in] bSelected If true only selected items are compared.
135 void CDiffThread::SetCompareSelected(bool bSelected /*=false*/)
137 m_bOnlyRequested = bSelected;
141 * @brief Returns thread's current state
143 unsigned CDiffThread::GetThreadState() const
145 return m_pDiffParm->nThreadState;
149 * @brief Item collection thread function.
151 * This thread is responsible for finding and collecting all items to compare
153 * @param [in] lpParam Pointer to parameter structure.
154 * @return Thread's return value.
156 static void DiffThreadCollect(void *pParam)
159 DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
161 assert(myStruct->bOnlyRequested == false);
163 // Stash abortable interface into context
164 myStruct->context->SetAbortable(myStruct->m_pAbortgate);
166 bool casesensitive = false;
167 int depth = myStruct->context->m_bRecursive ? -1 : 0;
169 paths = myStruct->context->GetNormalizedPaths();
171 String subdir[3] = {_T(""), _T(""), _T("")}; // blank to start at roots specified in diff context
173 // Build results list (except delaying file comparisons until below)
174 DirScan_GetItems(paths, subdir, myStruct,
175 casesensitive, depth, NULL, myStruct->context->m_bWalkUniques);
177 // ReleaseSemaphore() once again to signal that collect phase is ready
178 myStruct->pSemaphore->set();
180 // Send message to UI to update
181 int event = CDiffThread::EVENT_COLLECT_COMPLETED;
182 myStruct->m_listeners.notify(myStruct, event);
186 * @brief Folder compare thread function.
188 * Compares items in item list. After compare is ready
189 * sends message to UI so UI can update itself.
190 * @param [in] lpParam Pointer to parameter structure.
191 * @return Thread's return value.
193 static void DiffThreadCompare(void *pParam)
195 DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
197 // Stash abortable interface into context
198 myStruct->context->SetAbortable(myStruct->m_pAbortgate);
200 myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
202 // Now do all pending file comparisons
203 if (myStruct->bOnlyRequested)
204 DirScan_CompareRequestedItems(myStruct, 0);
206 DirScan_CompareItems(myStruct, 0);
208 myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_IDLE);
210 // Send message to UI to update
211 myStruct->nThreadState = CDiffThread::THREAD_COMPLETED;
212 int event = CDiffThread::EVENT_COMPARE_COMPLETED;
213 myStruct->m_listeners.notify(myStruct, event);