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
22 // ID line follows -- this is updated by SVN
23 // $Id: DiffThread.cpp 6910 2009-07-12 09:06:54Z kimmov $
25 #include "DiffThread.h"
28 #include <Poco/Thread.h>
29 #include <Poco/Semaphore.h>
30 #include "UnicodeString.h"
31 #include "DiffContext.h"
33 #include "DiffItemList.h"
34 #include "PathContext.h"
35 #include "CompareStats.h"
36 #include "IAbortable.h"
39 using Poco::Semaphore;
42 static void DiffThreadCollect(void *lpParam);
43 static void DiffThreadCompare(void *lpParam);
45 /** @brief abort handler for CDiffThread -- just a gateway to CDiffThread */
46 class DiffThreadAbortable : public IAbortable
48 // Implement DirScan's IAbortable
50 virtual bool ShouldAbort() const { return m_diffthread->ShouldAbort(); }
52 // All this object does is forward ShouldAbort calls to its containing CDiffThread
54 DiffThreadAbortable(CDiffThread * diffthread) : m_diffthread(diffthread) { }
55 CDiffThread * m_diffthread;
59 * @brief Default constructor.
61 CDiffThread::CDiffThread()
62 : m_pDiffContext(NULL)
64 , m_pDiffParm(new DiffFuncStruct)
66 m_pAbortgate.reset(new DiffThreadAbortable(this));
70 * @brief Destructor, release resources.
72 CDiffThread::~CDiffThread()
74 delete m_pDiffParm->pSemaphore;
78 * @brief Sets context pointer forwarded to thread.
79 * @param [in] pCtx Pointer to compare context.
81 void CDiffThread::SetContext(CDiffContext * pCtx)
83 m_pDiffContext = pCtx;
87 * @brief runtime interface for child thread, called on child thread
89 bool CDiffThread::ShouldAbort() const
95 * @brief Start and run directory compare thread.
96 * @return Success (1) or error for thread. Currently always 1.
98 unsigned CDiffThread::CompareDirectories()
100 assert(m_pDiffParm->nThreadState != THREAD_COMPARING);
102 m_pDiffParm->context = m_pDiffContext;
103 m_pDiffParm->m_pAbortgate = m_pAbortgate.get();
104 m_pDiffParm->bOnlyRequested = m_bOnlyRequested;
107 m_pDiffParm->nThreadState = THREAD_COMPARING;
109 delete m_pDiffParm->pSemaphore;
110 m_pDiffParm->pSemaphore = new Semaphore(0, LONG_MAX);
112 m_pDiffParm->context->m_pCompareStats->SetCompareState(CompareStats::STATE_START);
114 if (m_bOnlyRequested == false)
115 m_threads[0].start(DiffThreadCollect, m_pDiffParm.get());
116 m_threads[1].start(DiffThreadCompare, m_pDiffParm.get());
122 * @brief Selects to compare all or only selected items.
123 * @param [in] bSelected If true only selected items are compared.
125 void CDiffThread::SetCompareSelected(bool bSelected /*=false*/)
127 m_bOnlyRequested = bSelected;
131 * @brief Returns thread's current state
133 unsigned CDiffThread::GetThreadState() const
135 return m_pDiffParm->nThreadState;
139 * @brief Item collection thread function.
141 * This thread is responsible for finding and collecting all items to compare
143 * @param [in] lpParam Pointer to parameter structure.
144 * @return Thread's return value.
146 static void DiffThreadCollect(void *pParam)
149 DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
151 assert(myStruct->bOnlyRequested == false);
153 // Stash abortable interface into context
154 myStruct->context->SetAbortable(myStruct->m_pAbortgate);
156 bool casesensitive = false;
157 int depth = myStruct->context->m_bRecursive ? -1 : 0;
159 paths = myStruct->context->GetNormalizedPaths();
161 String subdir[3] = {_T(""), _T(""), _T("")}; // blank to start at roots specified in diff context
163 // Build results list (except delaying file comparisons until below)
164 DirScan_GetItems(paths, subdir, myStruct,
165 casesensitive, depth, NULL, myStruct->context->m_bWalkUniques);
167 // ReleaseSemaphore() once again to signal that collect phase is ready
168 myStruct->pSemaphore->set();
170 // Send message to UI to update
171 int event = CDiffThread::EVENT_COLLECT_COMPLETED;
172 myStruct->m_listeners.notify(myStruct, event);
176 * @brief Folder compare thread function.
178 * Compares items in item list. After compare is ready
179 * sends message to UI so UI can update itself.
180 * @param [in] lpParam Pointer to parameter structure.
181 * @return Thread's return value.
183 static void DiffThreadCompare(void *pParam)
185 DiffFuncStruct *myStruct = static_cast<DiffFuncStruct *>(pParam);
187 // Stash abortable interface into context
188 myStruct->context->SetAbortable(myStruct->m_pAbortgate);
190 myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
192 // Now do all pending file comparisons
193 if (myStruct->bOnlyRequested)
194 DirScan_CompareRequestedItems(myStruct, 0);
196 DirScan_CompareItems(myStruct, 0);
198 myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_IDLE);
200 // Send message to UI to update
201 myStruct->nThreadState = CDiffThread::THREAD_COMPLETED;
202 int event = CDiffThread::EVENT_COMPARE_COMPLETED;
203 myStruct->m_listeners.notify(myStruct, event);