1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*efeef26fSAndrew Rist  * distributed with this work for additional information
6*efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*efeef26fSAndrew Rist  *
11*efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*efeef26fSAndrew Rist  *
13*efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17*efeef26fSAndrew Rist  * specific language governing permissions and limitations
18*efeef26fSAndrew Rist  * under the License.
19*efeef26fSAndrew Rist  *
20*efeef26fSAndrew Rist  *************************************************************/
21*efeef26fSAndrew Rist 
22*efeef26fSAndrew Rist 
23cdf0e10cSrcweir #include "precompiled_sw.hxx"
24cdf0e10cSrcweir #include <finalthreadmanager.hxx>
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #ifndef _OSL_THREAD_HXX_
27cdf0e10cSrcweir #include <osl/thread.hxx>
28cdf0e10cSrcweir #endif
29cdf0e10cSrcweir #include <errhdl.hxx>
30cdf0e10cSrcweir #include <pausethreadstarting.hxx>
31cdf0e10cSrcweir #include <swthreadjoiner.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <com/sun/star/frame/XDesktop.hpp>
34cdf0e10cSrcweir #include <rtl/ustring.hxx>
35cdf0e10cSrcweir #include <com/sun/star/frame/XFramesSupplier.hpp>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir namespace css = ::com::sun::star;
38cdf0e10cSrcweir 
39cdf0e10cSrcweir /** thread to cancel a give list of cancellable jobs
40cdf0e10cSrcweir 
41cdf0e10cSrcweir     helper class for FinalThreadManager
42cdf0e10cSrcweir 
43cdf0e10cSrcweir     @author OD
44cdf0e10cSrcweir */
45cdf0e10cSrcweir class CancelJobsThread : public osl::Thread
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     public:
CancelJobsThread(std::list<css::uno::Reference<css::util::XCancellable>> aJobs)48cdf0e10cSrcweir         CancelJobsThread( std::list< css::uno::Reference< css::util::XCancellable > > aJobs )
49cdf0e10cSrcweir             : osl::Thread(),
50cdf0e10cSrcweir               maMutex(),
51cdf0e10cSrcweir               maJobs( aJobs ),
52cdf0e10cSrcweir               mbAllJobsCancelled( false ),
53cdf0e10cSrcweir               mbStopped( false )
54cdf0e10cSrcweir         {
55cdf0e10cSrcweir         }
56cdf0e10cSrcweir 
~CancelJobsThread()57cdf0e10cSrcweir         virtual ~CancelJobsThread() {}
58cdf0e10cSrcweir 
59cdf0e10cSrcweir         void addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs );
60cdf0e10cSrcweir 
61cdf0e10cSrcweir         bool allJobsCancelled() const;
62cdf0e10cSrcweir 
63cdf0e10cSrcweir         void stopWhenAllJobsCancelled();
64cdf0e10cSrcweir 
65cdf0e10cSrcweir     private:
66cdf0e10cSrcweir 
67cdf0e10cSrcweir         bool existJobs() const;
68cdf0e10cSrcweir 
69cdf0e10cSrcweir         css::uno::Reference< css::util::XCancellable > getNextJob();
70cdf0e10cSrcweir 
71cdf0e10cSrcweir         bool stopped() const;
72cdf0e10cSrcweir 
73cdf0e10cSrcweir         virtual void SAL_CALL run();
74cdf0e10cSrcweir 
75cdf0e10cSrcweir         mutable osl::Mutex maMutex;
76cdf0e10cSrcweir 
77cdf0e10cSrcweir         std::list< css::uno::Reference< css::util::XCancellable > > maJobs;
78cdf0e10cSrcweir 
79cdf0e10cSrcweir         bool mbAllJobsCancelled;
80cdf0e10cSrcweir         bool mbStopped;
81cdf0e10cSrcweir };
82cdf0e10cSrcweir 
addJobs(std::list<css::uno::Reference<css::util::XCancellable>> & rJobs)83cdf0e10cSrcweir void CancelJobsThread::addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
86cdf0e10cSrcweir 
87cdf0e10cSrcweir     maJobs.insert( maJobs.end(), rJobs.begin(), rJobs.end() );
88cdf0e10cSrcweir     mbAllJobsCancelled = !maJobs.empty();
89cdf0e10cSrcweir }
90cdf0e10cSrcweir 
existJobs() const91cdf0e10cSrcweir bool CancelJobsThread::existJobs() const
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     return !maJobs.empty();
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
allJobsCancelled() const98cdf0e10cSrcweir bool CancelJobsThread::allJobsCancelled() const
99cdf0e10cSrcweir {
100cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     return maJobs.empty() && mbAllJobsCancelled;
103cdf0e10cSrcweir }
stopWhenAllJobsCancelled()104cdf0e10cSrcweir void CancelJobsThread::stopWhenAllJobsCancelled()
105cdf0e10cSrcweir {
106cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     mbStopped = true;
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
getNextJob()111cdf0e10cSrcweir css::uno::Reference< css::util::XCancellable > CancelJobsThread::getNextJob()
112cdf0e10cSrcweir {
113cdf0e10cSrcweir     css::uno::Reference< css::util::XCancellable > xRet;
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     {
116cdf0e10cSrcweir         osl::MutexGuard aGuard(maMutex);
117cdf0e10cSrcweir 
118cdf0e10cSrcweir         if ( !maJobs.empty() )
119cdf0e10cSrcweir         {
120cdf0e10cSrcweir             xRet = maJobs.front();
121cdf0e10cSrcweir             maJobs.pop_front();
122cdf0e10cSrcweir         }
123cdf0e10cSrcweir     }
124cdf0e10cSrcweir 
125cdf0e10cSrcweir     return xRet;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir 
stopped() const128cdf0e10cSrcweir bool CancelJobsThread::stopped() const
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
131cdf0e10cSrcweir 
132cdf0e10cSrcweir     return mbStopped;
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
run()135cdf0e10cSrcweir void SAL_CALL CancelJobsThread::run()
136cdf0e10cSrcweir {
137cdf0e10cSrcweir     while ( !stopped() )
138cdf0e10cSrcweir     {
139cdf0e10cSrcweir         while ( existJobs() )
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             css::uno::Reference< css::util::XCancellable > aJob( getNextJob() );
142cdf0e10cSrcweir             if ( aJob.is() )
143cdf0e10cSrcweir             {
144cdf0e10cSrcweir                 aJob->cancel();
145cdf0e10cSrcweir             }
146cdf0e10cSrcweir         }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir         mbAllJobsCancelled = true;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir         {
151cdf0e10cSrcweir             TimeValue aSleepTime;
152cdf0e10cSrcweir             aSleepTime.Seconds = 1;
153cdf0e10cSrcweir             aSleepTime.Nanosec = 0;
154cdf0e10cSrcweir             osl_waitThread( &aSleepTime );
155cdf0e10cSrcweir         }
156cdf0e10cSrcweir     }
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir /** thread to terminate office, when all jobs are cancelled.
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     helper class for FinalThreadManager
162cdf0e10cSrcweir 
163cdf0e10cSrcweir     @author OD
164cdf0e10cSrcweir */
165cdf0e10cSrcweir class TerminateOfficeThread : public osl::Thread
166cdf0e10cSrcweir {
167cdf0e10cSrcweir     public:
TerminateOfficeThread(CancelJobsThread & rCancelJobsThread,css::uno::Reference<css::uno::XComponentContext> const & xContext)168cdf0e10cSrcweir         TerminateOfficeThread( CancelJobsThread& rCancelJobsThread,
169cdf0e10cSrcweir                                css::uno::Reference< css::uno::XComponentContext > const & xContext )
170cdf0e10cSrcweir             : osl::Thread(),
171cdf0e10cSrcweir               maMutex(),
172cdf0e10cSrcweir               mrCancelJobsThread( rCancelJobsThread ),
173cdf0e10cSrcweir               mbStopOfficeTermination( false ),
174cdf0e10cSrcweir               mxContext( xContext )
175cdf0e10cSrcweir         {
176cdf0e10cSrcweir         }
177cdf0e10cSrcweir 
~TerminateOfficeThread()178cdf0e10cSrcweir         virtual ~TerminateOfficeThread() {}
179cdf0e10cSrcweir 
180cdf0e10cSrcweir         void StopOfficeTermination();
181cdf0e10cSrcweir 
182cdf0e10cSrcweir     private:
183cdf0e10cSrcweir 
184cdf0e10cSrcweir         virtual void SAL_CALL run();
185cdf0e10cSrcweir         virtual void SAL_CALL onTerminated();
186cdf0e10cSrcweir 
187cdf0e10cSrcweir         bool OfficeTerminationStopped();
188cdf0e10cSrcweir 
189cdf0e10cSrcweir         void PerformOfficeTermination();
190cdf0e10cSrcweir 
191cdf0e10cSrcweir         osl::Mutex maMutex;
192cdf0e10cSrcweir 
193cdf0e10cSrcweir         const CancelJobsThread& mrCancelJobsThread;
194cdf0e10cSrcweir 
195cdf0e10cSrcweir         bool mbStopOfficeTermination;
196cdf0e10cSrcweir 
197cdf0e10cSrcweir         css::uno::Reference< css::uno::XComponentContext > mxContext;
198cdf0e10cSrcweir };
199cdf0e10cSrcweir 
StopOfficeTermination()200cdf0e10cSrcweir void TerminateOfficeThread::StopOfficeTermination()
201cdf0e10cSrcweir {
202cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     mbStopOfficeTermination = true;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
OfficeTerminationStopped()207cdf0e10cSrcweir bool TerminateOfficeThread::OfficeTerminationStopped()
208cdf0e10cSrcweir {
209cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
210cdf0e10cSrcweir 
211cdf0e10cSrcweir     return mbStopOfficeTermination;
212cdf0e10cSrcweir }
213cdf0e10cSrcweir 
run()214cdf0e10cSrcweir void SAL_CALL TerminateOfficeThread::run()
215cdf0e10cSrcweir {
216cdf0e10cSrcweir     while ( !OfficeTerminationStopped() )
217cdf0e10cSrcweir     {
218cdf0e10cSrcweir         osl::MutexGuard aGuard(maMutex);
219cdf0e10cSrcweir 
220cdf0e10cSrcweir         if ( mrCancelJobsThread.allJobsCancelled() )
221cdf0e10cSrcweir         {
222cdf0e10cSrcweir             break;
223cdf0e10cSrcweir         }
224cdf0e10cSrcweir     }
225cdf0e10cSrcweir 
226cdf0e10cSrcweir     if ( !OfficeTerminationStopped() )
227cdf0e10cSrcweir     {
228cdf0e10cSrcweir         PerformOfficeTermination();
229cdf0e10cSrcweir     }
230cdf0e10cSrcweir }
231cdf0e10cSrcweir 
PerformOfficeTermination()232cdf0e10cSrcweir void TerminateOfficeThread::PerformOfficeTermination()
233cdf0e10cSrcweir {
234cdf0e10cSrcweir     css::uno::Reference< css::frame::XFramesSupplier > xTasksSupplier(
235cdf0e10cSrcweir         mxContext->getServiceManager()->createInstanceWithContext(
236cdf0e10cSrcweir             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
237cdf0e10cSrcweir             mxContext ),
238cdf0e10cSrcweir         css::uno::UNO_QUERY );
239cdf0e10cSrcweir     if ( !xTasksSupplier.is() )
240cdf0e10cSrcweir     {
241cdf0e10cSrcweir         ASSERT( false, "<TerminateOfficeThread::PerformOfficeTermination()> - no XFramesSupplier!" );
242cdf0e10cSrcweir         return;
243cdf0e10cSrcweir     }
244cdf0e10cSrcweir 
245cdf0e10cSrcweir     css::uno::Reference< css::container::XElementAccess > xList( xTasksSupplier->getFrames(), css::uno::UNO_QUERY );
246cdf0e10cSrcweir     if ( !xList.is() )
247cdf0e10cSrcweir     {
248cdf0e10cSrcweir         ASSERT( false, "<TerminateOfficeThread::PerformOfficeTermination()> - no XElementAccess!" );
249cdf0e10cSrcweir         return;
250cdf0e10cSrcweir     }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     if ( !xList->hasElements() )
253cdf0e10cSrcweir     {
254cdf0e10cSrcweir         css::uno::Reference< css::frame::XDesktop > xDesktop( xTasksSupplier, css::uno::UNO_QUERY );
255cdf0e10cSrcweir         if ( xDesktop.is() && !OfficeTerminationStopped() )
256cdf0e10cSrcweir         {
257cdf0e10cSrcweir             xDesktop->terminate();
258cdf0e10cSrcweir         }
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir }
261cdf0e10cSrcweir 
onTerminated()262cdf0e10cSrcweir void SAL_CALL TerminateOfficeThread::onTerminated()
263cdf0e10cSrcweir {
264cdf0e10cSrcweir     if ( OfficeTerminationStopped() )
265cdf0e10cSrcweir     {
266cdf0e10cSrcweir         delete this;
267cdf0e10cSrcweir     }
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir 
271cdf0e10cSrcweir /** class FinalThreadManager
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     @author OD
274cdf0e10cSrcweir */
FinalThreadManager(css::uno::Reference<css::uno::XComponentContext> const & context)275cdf0e10cSrcweir FinalThreadManager::FinalThreadManager(css::uno::Reference< css::uno::XComponentContext > const & context)
276cdf0e10cSrcweir     : m_xContext(context),
277cdf0e10cSrcweir       maMutex(),
278cdf0e10cSrcweir       maThreads(),
279cdf0e10cSrcweir       mpCancelJobsThread( 0 ),
280cdf0e10cSrcweir       mpTerminateOfficeThread( 0 ),
281cdf0e10cSrcweir       mpPauseThreadStarting( 0 ),
282cdf0e10cSrcweir       mbRegisteredAtDesktop( false )
283cdf0e10cSrcweir {
284cdf0e10cSrcweir 
285cdf0e10cSrcweir }
286cdf0e10cSrcweir 
registerAsListenerAtDesktop()287cdf0e10cSrcweir void FinalThreadManager::registerAsListenerAtDesktop()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir     css::uno::Reference< css::frame::XDesktop > xDesktop(
290cdf0e10cSrcweir         m_xContext->getServiceManager()->createInstanceWithContext(
291cdf0e10cSrcweir             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
292cdf0e10cSrcweir             m_xContext ),
293cdf0e10cSrcweir         css::uno::UNO_QUERY );
294cdf0e10cSrcweir 
295cdf0e10cSrcweir     if ( xDesktop.is() )
296cdf0e10cSrcweir     {
297cdf0e10cSrcweir         xDesktop->addTerminateListener( css::uno::Reference< css::frame::XTerminateListener >( static_cast< cppu::OWeakObject* >( this ), css::uno::UNO_QUERY ) );
298cdf0e10cSrcweir     }
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
~FinalThreadManager()301cdf0e10cSrcweir FinalThreadManager::~FinalThreadManager()
302cdf0e10cSrcweir {
303cdf0e10cSrcweir     if ( mpPauseThreadStarting != 0 )
304cdf0e10cSrcweir     {
305cdf0e10cSrcweir         delete mpPauseThreadStarting;
306cdf0e10cSrcweir         mpPauseThreadStarting = 0;
307cdf0e10cSrcweir     }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     if ( mpTerminateOfficeThread != 0 )
310cdf0e10cSrcweir     {
311cdf0e10cSrcweir         mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
312cdf0e10cSrcweir         mpTerminateOfficeThread = 0;
313cdf0e10cSrcweir     }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir     if ( !maThreads.empty() )
316cdf0e10cSrcweir     {
317cdf0e10cSrcweir         ASSERT( false, "<FinalThreadManager::~FinalThreadManager()> - still registered jobs are existing -> perform cancellation" );
318cdf0e10cSrcweir         cancelAllJobs();
319cdf0e10cSrcweir     }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     if ( mpCancelJobsThread != 0 )
322cdf0e10cSrcweir     {
323cdf0e10cSrcweir         if ( !mpCancelJobsThread->allJobsCancelled() )
324cdf0e10cSrcweir         {
325cdf0e10cSrcweir             ASSERT( false, "<FinalThreadManager::~FinalThreadManager()> - cancellation of registered jobs not yet finished -> wait for its finish" );
326cdf0e10cSrcweir         }
327cdf0e10cSrcweir 
328cdf0e10cSrcweir         mpCancelJobsThread->stopWhenAllJobsCancelled();
329cdf0e10cSrcweir         mpCancelJobsThread->join();
330cdf0e10cSrcweir         delete mpCancelJobsThread;
331cdf0e10cSrcweir         mpCancelJobsThread = 0;
332cdf0e10cSrcweir     }
333cdf0e10cSrcweir }
334cdf0e10cSrcweir 
335cdf0e10cSrcweir // com.sun.star.uno.XServiceInfo:
getImplementationName()336cdf0e10cSrcweir ::rtl::OUString SAL_CALL FinalThreadManager::getImplementationName() throw (css::uno::RuntimeException)
337cdf0e10cSrcweir {
338cdf0e10cSrcweir     return comp_FinalThreadManager::_getImplementationName();
339cdf0e10cSrcweir }
340cdf0e10cSrcweir 
supportsService(::rtl::OUString const & serviceName)341cdf0e10cSrcweir ::sal_Bool SAL_CALL FinalThreadManager::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException)
342cdf0e10cSrcweir {
343cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > serviceNames = comp_FinalThreadManager::_getSupportedServiceNames();
344cdf0e10cSrcweir     for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
345cdf0e10cSrcweir         if (serviceNames[i] == serviceName)
346cdf0e10cSrcweir             return sal_True;
347cdf0e10cSrcweir     }
348cdf0e10cSrcweir     return sal_False;
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
getSupportedServiceNames()351cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > SAL_CALL FinalThreadManager::getSupportedServiceNames() throw (css::uno::RuntimeException)
352cdf0e10cSrcweir {
353cdf0e10cSrcweir     return comp_FinalThreadManager::_getSupportedServiceNames();
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir // ::com::sun::star::util::XJobManager:
registerJob(const css::uno::Reference<css::util::XCancellable> & Job)357cdf0e10cSrcweir void SAL_CALL FinalThreadManager::registerJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
358cdf0e10cSrcweir {
359cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
360cdf0e10cSrcweir 
361cdf0e10cSrcweir     maThreads.push_back( Job );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     if ( !mbRegisteredAtDesktop )
364cdf0e10cSrcweir     {
365cdf0e10cSrcweir         registerAsListenerAtDesktop();
366cdf0e10cSrcweir         mbRegisteredAtDesktop = true;
367cdf0e10cSrcweir     }
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
releaseJob(const css::uno::Reference<css::util::XCancellable> & Job)370cdf0e10cSrcweir void SAL_CALL FinalThreadManager::releaseJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
371cdf0e10cSrcweir {
372cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
373cdf0e10cSrcweir 
374cdf0e10cSrcweir     maThreads.remove( Job );
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
cancelAllJobs()377cdf0e10cSrcweir void SAL_CALL FinalThreadManager::cancelAllJobs() throw (css::uno::RuntimeException)
378cdf0e10cSrcweir {
379cdf0e10cSrcweir     std::list< css::uno::Reference< css::util::XCancellable > > aThreads;
380cdf0e10cSrcweir     {
381cdf0e10cSrcweir         osl::MutexGuard aGuard(maMutex);
382cdf0e10cSrcweir 
383cdf0e10cSrcweir         aThreads.insert( aThreads.end(), maThreads.begin(), maThreads.end() );
384cdf0e10cSrcweir         maThreads.clear();
385cdf0e10cSrcweir     }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir     if ( !aThreads.empty() )
388cdf0e10cSrcweir     {
389cdf0e10cSrcweir         osl::MutexGuard aGuard(maMutex);
390cdf0e10cSrcweir 
391cdf0e10cSrcweir         if ( mpCancelJobsThread == 0 )
392cdf0e10cSrcweir         {
393cdf0e10cSrcweir             mpCancelJobsThread = new CancelJobsThread( aThreads );;
394cdf0e10cSrcweir             if ( !mpCancelJobsThread->create() )
395cdf0e10cSrcweir             {
396cdf0e10cSrcweir                 // error handling
397cdf0e10cSrcweir                 // ASSERT( false, "<FinalThreadManager::cancelAllJobs()> - thread to cancel jobs can't be setup --> synchron cancellation of jobs" );
398cdf0e10cSrcweir                 delete mpCancelJobsThread;
399cdf0e10cSrcweir                 mpCancelJobsThread = 0;
400cdf0e10cSrcweir                 while ( !aThreads.empty() )
401cdf0e10cSrcweir                 {
402cdf0e10cSrcweir                     aThreads.front()->cancel();
403cdf0e10cSrcweir                     aThreads.pop_front();
404cdf0e10cSrcweir                 }
405cdf0e10cSrcweir             }
406cdf0e10cSrcweir         }
407cdf0e10cSrcweir         else
408cdf0e10cSrcweir         {
409cdf0e10cSrcweir             mpCancelJobsThread->addJobs( aThreads );
410cdf0e10cSrcweir         }
411cdf0e10cSrcweir     }
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir // ::com::sun::star::frame::XTerminateListener
queryTermination(const css::lang::EventObject &)415cdf0e10cSrcweir void SAL_CALL FinalThreadManager::queryTermination( const css::lang::EventObject& ) throw (css::frame::TerminationVetoException, css::uno::RuntimeException)
416cdf0e10cSrcweir {
417cdf0e10cSrcweir     osl::MutexGuard aGuard(maMutex);
418cdf0e10cSrcweir 
419cdf0e10cSrcweir     cancelAllJobs();
420cdf0e10cSrcweir     // Sleep 1 second to give the thread for job cancellation some time.
421cdf0e10cSrcweir     // Probably, all started threads have already finished its work.
422cdf0e10cSrcweir     if ( mpCancelJobsThread != 0 &&
423cdf0e10cSrcweir          !mpCancelJobsThread->allJobsCancelled() )
424cdf0e10cSrcweir     {
425cdf0e10cSrcweir         TimeValue aSleepTime;
426cdf0e10cSrcweir         aSleepTime.Seconds = 1;
427cdf0e10cSrcweir         aSleepTime.Nanosec = 0;
428cdf0e10cSrcweir         osl_waitThread( &aSleepTime );
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir 
431cdf0e10cSrcweir     if ( mpCancelJobsThread != 0 &&
432cdf0e10cSrcweir          !mpCancelJobsThread->allJobsCancelled() )
433cdf0e10cSrcweir     {
434cdf0e10cSrcweir         if ( mpTerminateOfficeThread != 0 )
435cdf0e10cSrcweir         {
436cdf0e10cSrcweir             if ( mpTerminateOfficeThread->isRunning() )
437cdf0e10cSrcweir             {
438cdf0e10cSrcweir                 mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
439cdf0e10cSrcweir             }
440cdf0e10cSrcweir             else
441cdf0e10cSrcweir             {
442cdf0e10cSrcweir                 delete mpTerminateOfficeThread;
443cdf0e10cSrcweir             }
444cdf0e10cSrcweir             mpTerminateOfficeThread = 0;
445cdf0e10cSrcweir         }
446cdf0e10cSrcweir         mpTerminateOfficeThread = new TerminateOfficeThread( *mpCancelJobsThread,
447cdf0e10cSrcweir                                                  m_xContext );
448cdf0e10cSrcweir         if ( !mpTerminateOfficeThread->create() )
449cdf0e10cSrcweir         {
450cdf0e10cSrcweir             // ASSERT( false, "FinalThreadManager::queryTermination(..) - thread to terminate office can't be started!" );
451cdf0e10cSrcweir             delete mpTerminateOfficeThread;
452cdf0e10cSrcweir             mpTerminateOfficeThread = 0;
453cdf0e10cSrcweir         }
454cdf0e10cSrcweir 
455cdf0e10cSrcweir         throw css::frame::TerminationVetoException();
456cdf0e10cSrcweir     }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir     mpPauseThreadStarting = new SwPauseThreadStarting();
459cdf0e10cSrcweir 
460cdf0e10cSrcweir     return;
461cdf0e10cSrcweir }
462cdf0e10cSrcweir 
cancelTermination(const css::lang::EventObject &)463cdf0e10cSrcweir void SAL_CALL FinalThreadManager::cancelTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
464cdf0e10cSrcweir {
465cdf0e10cSrcweir     if ( mpPauseThreadStarting != 0 )
466cdf0e10cSrcweir     {
467cdf0e10cSrcweir         delete mpPauseThreadStarting;
468cdf0e10cSrcweir         mpPauseThreadStarting = 0;
469cdf0e10cSrcweir     }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir     return;
472cdf0e10cSrcweir }
473cdf0e10cSrcweir 
notifyTermination(const css::lang::EventObject &)474cdf0e10cSrcweir void SAL_CALL FinalThreadManager::notifyTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
475cdf0e10cSrcweir {
476cdf0e10cSrcweir     if ( mpTerminateOfficeThread != 0 )
477cdf0e10cSrcweir     {
478cdf0e10cSrcweir         if ( mpTerminateOfficeThread->isRunning() )
479cdf0e10cSrcweir         {
480cdf0e10cSrcweir             // ASSERT( false, "<FinalThreadManager::notifyTermination()> - office termination thread still running!" );
481cdf0e10cSrcweir             mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
482cdf0e10cSrcweir         }
483cdf0e10cSrcweir         else
484cdf0e10cSrcweir         {
485cdf0e10cSrcweir             delete mpTerminateOfficeThread;
486cdf0e10cSrcweir         }
487cdf0e10cSrcweir         mpTerminateOfficeThread = 0;
488cdf0e10cSrcweir     }
489cdf0e10cSrcweir 
490cdf0e10cSrcweir     if ( !maThreads.empty() )
491cdf0e10cSrcweir     {
492cdf0e10cSrcweir         // ASSERT( false, "<FinalThreadManager::notifyTermination()> - still registered jobs are existing" );
493cdf0e10cSrcweir         cancelAllJobs();
494cdf0e10cSrcweir     }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir     if ( mpCancelJobsThread != 0 )
497cdf0e10cSrcweir     {
498cdf0e10cSrcweir         if ( !mpCancelJobsThread->allJobsCancelled() )
499cdf0e10cSrcweir         {
500cdf0e10cSrcweir             // ASSERT( false, "<FinalThreadManager::notifyTermination()> - cancellation of registered jobs not yet finished -> wait for its finish" );
501cdf0e10cSrcweir         }
502cdf0e10cSrcweir 
503cdf0e10cSrcweir         mpCancelJobsThread->stopWhenAllJobsCancelled();
504cdf0e10cSrcweir         mpCancelJobsThread->join();
505cdf0e10cSrcweir         delete mpCancelJobsThread;
506cdf0e10cSrcweir         mpCancelJobsThread = 0;
507cdf0e10cSrcweir     }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir     // get reference of this
510cdf0e10cSrcweir     css::uno::Reference< css::uno::XInterface > aOwnRef( static_cast< cppu::OWeakObject* >( this ));
511cdf0e10cSrcweir     // notify <SwThreadJoiner> to release its reference
512cdf0e10cSrcweir     SwThreadJoiner::ReleaseThreadJoiner();
513cdf0e10cSrcweir }
514cdf0e10cSrcweir 
515cdf0e10cSrcweir // ::com::sun:star::lang::XEventListener (inherited via com::sun::star::frame::XTerminateListener)
disposing(const css::lang::EventObject &)516cdf0e10cSrcweir void SAL_CALL FinalThreadManager::disposing( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
517cdf0e10cSrcweir {
518cdf0e10cSrcweir     // nothing to do, because instance doesn't hold any references of observed objects
519cdf0e10cSrcweir }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir // component helper namespace
522cdf0e10cSrcweir namespace comp_FinalThreadManager {
523cdf0e10cSrcweir 
_getImplementationName()524cdf0e10cSrcweir     ::rtl::OUString SAL_CALL _getImplementationName()
525cdf0e10cSrcweir     {
526cdf0e10cSrcweir         return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
527cdf0e10cSrcweir             "com.sun.star.util.comp.FinalThreadManager"));
528cdf0e10cSrcweir     }
529cdf0e10cSrcweir 
_getSupportedServiceNames()530cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
531cdf0e10cSrcweir     {
532cdf0e10cSrcweir         css::uno::Sequence< ::rtl::OUString > s(1);
533cdf0e10cSrcweir         s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
534cdf0e10cSrcweir             "com.sun.star.util.JobManager"));
535cdf0e10cSrcweir         return s;
536cdf0e10cSrcweir     }
537cdf0e10cSrcweir 
_create(const css::uno::Reference<css::uno::XComponentContext> & context)538cdf0e10cSrcweir     css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
539cdf0e10cSrcweir         const css::uno::Reference< css::uno::XComponentContext > & context)
540cdf0e10cSrcweir             SAL_THROW((css::uno::Exception))
541cdf0e10cSrcweir     {
542cdf0e10cSrcweir         return static_cast< ::cppu::OWeakObject * >(new FinalThreadManager(context));
543cdf0e10cSrcweir     }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir } // closing component helper namespace
546