merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / docnode / finalthreadmanager.cxx
blob442870a19452f95fd3285361a53b7cd0684115e9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: finalthreadmanager.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "precompiled_sw.hxx"
31 #include <finalthreadmanager.hxx>
33 #ifndef _OSL_THREAD_HXX_
34 #include <osl/thread.hxx>
35 #endif
36 #include <errhdl.hxx>
37 #include <pausethreadstarting.hxx>
38 #include <swthreadjoiner.hxx>
40 #include <com/sun/star/frame/XDesktop.hpp>
41 #include <rtl/ustring.hxx>
42 #include <com/sun/star/frame/XFramesSupplier.hpp>
44 namespace css = ::com::sun::star;
46 /** thread to cancel a give list of cancellable jobs
48 helper class for FinalThreadManager
50 @author OD
52 class CancelJobsThread : public osl::Thread
54 public:
55 CancelJobsThread( std::list< css::uno::Reference< css::util::XCancellable > > aJobs )
56 : osl::Thread(),
57 maMutex(),
58 maJobs( aJobs ),
59 mbAllJobsCancelled( false ),
60 mbStopped( false )
64 virtual ~CancelJobsThread() {}
66 void addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs );
68 bool allJobsCancelled() const;
70 void stopWhenAllJobsCancelled();
72 private:
74 bool existJobs() const;
76 css::uno::Reference< css::util::XCancellable > getNextJob();
78 bool stopped() const;
80 virtual void SAL_CALL run();
82 mutable osl::Mutex maMutex;
84 std::list< css::uno::Reference< css::util::XCancellable > > maJobs;
86 bool mbAllJobsCancelled;
87 bool mbStopped;
90 void CancelJobsThread::addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs )
92 osl::MutexGuard aGuard(maMutex);
94 maJobs.insert( maJobs.end(), rJobs.begin(), rJobs.end() );
95 mbAllJobsCancelled = !maJobs.empty();
98 bool CancelJobsThread::existJobs() const
100 osl::MutexGuard aGuard(maMutex);
102 return !maJobs.empty();
105 bool CancelJobsThread::allJobsCancelled() const
107 osl::MutexGuard aGuard(maMutex);
109 return maJobs.empty() && mbAllJobsCancelled;
111 void CancelJobsThread::stopWhenAllJobsCancelled()
113 osl::MutexGuard aGuard(maMutex);
115 mbStopped = true;
118 css::uno::Reference< css::util::XCancellable > CancelJobsThread::getNextJob()
120 css::uno::Reference< css::util::XCancellable > xRet;
123 osl::MutexGuard aGuard(maMutex);
125 if ( !maJobs.empty() )
127 xRet = maJobs.front();
128 maJobs.pop_front();
132 return xRet;
135 bool CancelJobsThread::stopped() const
137 osl::MutexGuard aGuard(maMutex);
139 return mbStopped;
142 void SAL_CALL CancelJobsThread::run()
144 while ( !stopped() )
146 while ( existJobs() )
148 css::uno::Reference< css::util::XCancellable > aJob( getNextJob() );
149 if ( aJob.is() )
151 aJob->cancel();
155 mbAllJobsCancelled = true;
158 TimeValue aSleepTime;
159 aSleepTime.Seconds = 1;
160 aSleepTime.Nanosec = 0;
161 osl_waitThread( &aSleepTime );
166 /** thread to terminate office, when all jobs are cancelled.
168 helper class for FinalThreadManager
170 @author OD
172 class TerminateOfficeThread : public osl::Thread
174 public:
175 TerminateOfficeThread( CancelJobsThread& rCancelJobsThread,
176 css::uno::Reference< css::uno::XComponentContext > const & xContext )
177 : osl::Thread(),
178 maMutex(),
179 mrCancelJobsThread( rCancelJobsThread ),
180 mbStopOfficeTermination( false ),
181 mxContext( xContext )
185 virtual ~TerminateOfficeThread() {}
187 void StopOfficeTermination();
189 private:
191 virtual void SAL_CALL run();
192 virtual void SAL_CALL onTerminated();
194 bool OfficeTerminationStopped();
196 void PerformOfficeTermination();
198 osl::Mutex maMutex;
200 const CancelJobsThread& mrCancelJobsThread;
202 bool mbStopOfficeTermination;
204 css::uno::Reference< css::uno::XComponentContext > mxContext;
207 void TerminateOfficeThread::StopOfficeTermination()
209 osl::MutexGuard aGuard(maMutex);
211 mbStopOfficeTermination = true;
214 bool TerminateOfficeThread::OfficeTerminationStopped()
216 osl::MutexGuard aGuard(maMutex);
218 return mbStopOfficeTermination;
221 void SAL_CALL TerminateOfficeThread::run()
223 while ( !OfficeTerminationStopped() )
225 osl::MutexGuard aGuard(maMutex);
227 if ( mrCancelJobsThread.allJobsCancelled() )
229 break;
233 if ( !OfficeTerminationStopped() )
235 PerformOfficeTermination();
239 void TerminateOfficeThread::PerformOfficeTermination()
241 css::uno::Reference< css::frame::XFramesSupplier > xTasksSupplier(
242 mxContext->getServiceManager()->createInstanceWithContext(
243 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
244 mxContext ),
245 css::uno::UNO_QUERY );
246 if ( !xTasksSupplier.is() )
248 ASSERT( false, "<TerminateOfficeThread::PerformOfficeTermination()> - no XFramesSupplier!" );
249 return;
252 css::uno::Reference< css::container::XElementAccess > xList( xTasksSupplier->getFrames(), css::uno::UNO_QUERY );
253 if ( !xList.is() )
255 ASSERT( false, "<TerminateOfficeThread::PerformOfficeTermination()> - no XElementAccess!" );
256 return;
259 if ( !xList->hasElements() )
261 css::uno::Reference< css::frame::XDesktop > xDesktop( xTasksSupplier, css::uno::UNO_QUERY );
262 if ( xDesktop.is() && !OfficeTerminationStopped() )
264 xDesktop->terminate();
269 void SAL_CALL TerminateOfficeThread::onTerminated()
271 if ( OfficeTerminationStopped() )
273 delete this;
278 /** class FinalThreadManager
280 @author OD
282 FinalThreadManager::FinalThreadManager(css::uno::Reference< css::uno::XComponentContext > const & context)
283 : m_xContext(context),
284 maMutex(),
285 maThreads(),
286 mpCancelJobsThread( 0 ),
287 mpTerminateOfficeThread( 0 ),
288 mpPauseThreadStarting( 0 ),
289 mbRegisteredAtDesktop( false )
294 void FinalThreadManager::registerAsListenerAtDesktop()
296 css::uno::Reference< css::frame::XDesktop > xDesktop(
297 m_xContext->getServiceManager()->createInstanceWithContext(
298 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
299 m_xContext ),
300 css::uno::UNO_QUERY );
302 if ( xDesktop.is() )
304 xDesktop->addTerminateListener( css::uno::Reference< css::frame::XTerminateListener >( static_cast< cppu::OWeakObject* >( this ), css::uno::UNO_QUERY ) );
308 FinalThreadManager::~FinalThreadManager()
310 if ( mpPauseThreadStarting != 0 )
312 delete mpPauseThreadStarting;
313 mpPauseThreadStarting = 0;
316 if ( mpTerminateOfficeThread != 0 )
318 mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
319 mpTerminateOfficeThread = 0;
322 if ( !maThreads.empty() )
324 ASSERT( false, "<FinalThreadManager::~FinalThreadManager()> - still registered jobs are existing -> perform cancellation" );
325 cancelAllJobs();
328 if ( mpCancelJobsThread != 0 )
330 if ( !mpCancelJobsThread->allJobsCancelled() )
332 ASSERT( false, "<FinalThreadManager::~FinalThreadManager()> - cancellation of registered jobs not yet finished -> wait for its finish" );
335 mpCancelJobsThread->stopWhenAllJobsCancelled();
336 mpCancelJobsThread->join();
337 delete mpCancelJobsThread;
338 mpCancelJobsThread = 0;
342 // com.sun.star.uno.XServiceInfo:
343 ::rtl::OUString SAL_CALL FinalThreadManager::getImplementationName() throw (css::uno::RuntimeException)
345 return comp_FinalThreadManager::_getImplementationName();
348 ::sal_Bool SAL_CALL FinalThreadManager::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException)
350 css::uno::Sequence< ::rtl::OUString > serviceNames = comp_FinalThreadManager::_getSupportedServiceNames();
351 for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
352 if (serviceNames[i] == serviceName)
353 return sal_True;
355 return sal_False;
358 css::uno::Sequence< ::rtl::OUString > SAL_CALL FinalThreadManager::getSupportedServiceNames() throw (css::uno::RuntimeException)
360 return comp_FinalThreadManager::_getSupportedServiceNames();
363 // ::com::sun::star::util::XJobManager:
364 void SAL_CALL FinalThreadManager::registerJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
366 osl::MutexGuard aGuard(maMutex);
368 maThreads.push_back( Job );
370 if ( !mbRegisteredAtDesktop )
372 registerAsListenerAtDesktop();
373 mbRegisteredAtDesktop = true;
377 void SAL_CALL FinalThreadManager::releaseJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
379 osl::MutexGuard aGuard(maMutex);
381 maThreads.remove( Job );
384 void SAL_CALL FinalThreadManager::cancelAllJobs() throw (css::uno::RuntimeException)
386 std::list< css::uno::Reference< css::util::XCancellable > > aThreads;
388 osl::MutexGuard aGuard(maMutex);
390 aThreads.insert( aThreads.end(), maThreads.begin(), maThreads.end() );
391 maThreads.clear();
394 if ( !aThreads.empty() )
396 osl::MutexGuard aGuard(maMutex);
398 if ( mpCancelJobsThread == 0 )
400 mpCancelJobsThread = new CancelJobsThread( aThreads );;
401 if ( !mpCancelJobsThread->create() )
403 // error handling
404 // ASSERT( false, "<FinalThreadManager::cancelAllJobs()> - thread to cancel jobs can't be setup --> synchron cancellation of jobs" );
405 delete mpCancelJobsThread;
406 mpCancelJobsThread = 0;
407 while ( !aThreads.empty() )
409 aThreads.front()->cancel();
410 aThreads.pop_front();
414 else
416 mpCancelJobsThread->addJobs( aThreads );
421 // ::com::sun::star::frame::XTerminateListener
422 void SAL_CALL FinalThreadManager::queryTermination( const css::lang::EventObject& ) throw (css::frame::TerminationVetoException, css::uno::RuntimeException)
424 osl::MutexGuard aGuard(maMutex);
426 cancelAllJobs();
427 // Sleep 1 second to give the thread for job cancellation some time.
428 // Probably, all started threads have already finished its work.
429 if ( mpCancelJobsThread != 0 &&
430 !mpCancelJobsThread->allJobsCancelled() )
432 TimeValue aSleepTime;
433 aSleepTime.Seconds = 1;
434 aSleepTime.Nanosec = 0;
435 osl_waitThread( &aSleepTime );
438 if ( mpCancelJobsThread != 0 &&
439 !mpCancelJobsThread->allJobsCancelled() )
441 if ( mpTerminateOfficeThread != 0 )
443 if ( mpTerminateOfficeThread->isRunning() )
445 mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
447 else
449 delete mpTerminateOfficeThread;
451 mpTerminateOfficeThread = 0;
453 mpTerminateOfficeThread = new TerminateOfficeThread( *mpCancelJobsThread,
454 m_xContext );
455 if ( !mpTerminateOfficeThread->create() )
457 // ASSERT( false, "FinalThreadManager::queryTermination(..) - thread to terminate office can't be started!" );
458 delete mpTerminateOfficeThread;
459 mpTerminateOfficeThread = 0;
462 throw css::frame::TerminationVetoException();
465 mpPauseThreadStarting = new SwPauseThreadStarting();
467 return;
470 void SAL_CALL FinalThreadManager::cancelTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
472 if ( mpPauseThreadStarting != 0 )
474 delete mpPauseThreadStarting;
475 mpPauseThreadStarting = 0;
478 return;
481 void SAL_CALL FinalThreadManager::notifyTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
483 if ( mpTerminateOfficeThread != 0 )
485 if ( mpTerminateOfficeThread->isRunning() )
487 // ASSERT( false, "<FinalThreadManager::notifyTermination()> - office termination thread still running!" );
488 mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
490 else
492 delete mpTerminateOfficeThread;
494 mpTerminateOfficeThread = 0;
497 if ( !maThreads.empty() )
499 // ASSERT( false, "<FinalThreadManager::notifyTermination()> - still registered jobs are existing" );
500 cancelAllJobs();
503 if ( mpCancelJobsThread != 0 )
505 if ( !mpCancelJobsThread->allJobsCancelled() )
507 // ASSERT( false, "<FinalThreadManager::notifyTermination()> - cancellation of registered jobs not yet finished -> wait for its finish" );
510 mpCancelJobsThread->stopWhenAllJobsCancelled();
511 mpCancelJobsThread->join();
512 delete mpCancelJobsThread;
513 mpCancelJobsThread = 0;
516 // get reference of this
517 css::uno::Reference< css::uno::XInterface > aOwnRef( static_cast< cppu::OWeakObject* >( this ));
518 // notify <SwThreadJoiner> to release its reference
519 SwThreadJoiner::ReleaseThreadJoiner();
522 // ::com::sun:star::lang::XEventListener (inherited via com::sun::star::frame::XTerminateListener)
523 void SAL_CALL FinalThreadManager::disposing( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
525 // nothing to do, because instance doesn't hold any references of observed objects
528 // component helper namespace
529 namespace comp_FinalThreadManager {
531 ::rtl::OUString SAL_CALL _getImplementationName()
533 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
534 "com.sun.star.util.comp.FinalThreadManager"));
537 css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
539 css::uno::Sequence< ::rtl::OUString > s(1);
540 s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
541 "com.sun.star.util.JobManager"));
542 return s;
545 css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
546 const css::uno::Reference< css::uno::XComponentContext > & context)
547 SAL_THROW((css::uno::Exception))
549 return static_cast< ::cppu::OWeakObject * >(new FinalThreadManager(context));
552 } // closing component helper namespace