merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / tools / LifeTime.cxx
blobefb0751d7feddb9133a79818b99a42da6325cc8a
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: LifeTime.cxx,v $
10 * $Revision: 1.6 $
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 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "LifeTime.hxx"
34 #include "macros.hxx"
35 #include <osl/diagnose.h>
37 #include <com/sun/star/util/XModifyListener.hpp>
38 #include <com/sun/star/util/XCloseListener.hpp>
40 using namespace ::com::sun::star;
42 namespace apphelper
44 //--------------------------
46 LifeTimeManager::LifeTimeManager( lang::XComponent* pComponent, sal_Bool bLongLastingCallsCancelable )
47 : m_aListenerContainer( m_aAccessMutex )
48 , m_pComponent(pComponent)
49 , m_bLongLastingCallsCancelable(bLongLastingCallsCancelable)
51 impl_init();
54 void LifeTimeManager::impl_init()
56 m_bDisposed = sal_False;
57 m_bInDispose = sal_False;
58 m_nAccessCount = 0;
59 m_nLongLastingCallCount = 0;
60 m_aNoAccessCountCondition.set();
61 m_aNoLongLastingCallCountCondition.set();
64 LifeTimeManager::~LifeTimeManager()
68 sal_Bool LifeTimeManager
69 ::impl_isDisposed()
71 if( m_bDisposed || m_bInDispose )
73 OSL_ENSURE( sal_False, "This component is already disposed " );
74 return sal_True;
76 return sal_False;
78 sal_Bool LifeTimeManager
79 ::impl_canStartApiCall()
81 if( impl_isDisposed() )
82 return sal_False; //behave passive if already disposed
84 //mutex is acquired
85 return sal_True;
88 void LifeTimeManager
89 ::impl_registerApiCall(sal_Bool bLongLastingCall)
91 //only allowed if not disposed
92 //do not acquire the mutex here because it will be acquired already
93 m_nAccessCount++;
94 if(m_nAccessCount==1)
95 //@todo? is it ok to wake some threads here while we have acquired the mutex?
96 m_aNoAccessCountCondition.reset();
98 if(bLongLastingCall)
99 m_nLongLastingCallCount++;
100 if(m_nLongLastingCallCount==1)
101 m_aNoLongLastingCallCountCondition.reset();
103 void LifeTimeManager
104 ::impl_unregisterApiCall(sal_Bool bLongLastingCall)
106 //Mutex needs to be acquired exactly ones
107 //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
109 OSL_ENSURE( m_nAccessCount>0, "access count mismatch" );
110 m_nAccessCount--;
111 if(bLongLastingCall)
112 m_nLongLastingCallCount--;
113 if( m_nLongLastingCallCount==0 )
115 m_aNoLongLastingCallCountCondition.set();
117 if( m_nAccessCount== 0)
119 m_aNoAccessCountCondition.set();
120 impl_apiCallCountReachedNull();
125 sal_Bool LifeTimeManager
126 ::dispose() throw(uno::RuntimeException)
128 //hold no mutex
130 osl::Guard< osl::Mutex > aGuard( m_aAccessMutex );
132 if( m_bDisposed || m_bInDispose )
134 OSL_TRACE( "This component is already disposed " );
135 return sal_False; //behave passive if already disposed
138 m_bInDispose = true;
139 //adding any listener is not allowed anymore
140 //new calls will not be accepted
141 //still running calls have the freedom to finish their work without crash
143 //no mutex is acquired
145 //--do the disposing of listeners after calling this method
147 uno::Reference< lang::XComponent > xComponent =
148 uno::Reference< lang::XComponent >(m_pComponent);;
149 if(xComponent.is())
151 // notify XCLoseListeners
152 lang::EventObject aEvent( xComponent );
153 m_aListenerContainer.disposeAndClear( aEvent );
157 //no mutex is acquired
159 osl::ClearableGuard< osl::Mutex > aGuard( m_aAccessMutex );
160 OSL_ENSURE( !m_bDisposed, "dispose was called already" );
161 m_bDisposed = sal_True;
162 aGuard.clear();
164 //no mutex is acquired
166 //wait until all still running calls have finished
167 //the accessCount cannot grow anymore, because all calls will return after checking m_bDisposed
168 m_aNoAccessCountCondition.wait();
170 //we are the only ones working on our data now
172 return sal_True;
173 //--release all resources and references after calling this method successful
176 //-----------------------------------------------------------------
178 CloseableLifeTimeManager::CloseableLifeTimeManager( ::com::sun::star::util::XCloseable* pCloseable
179 , ::com::sun::star::lang::XComponent* pComponent
180 , sal_Bool bLongLastingCallsCancelable )
181 : LifeTimeManager( pComponent, bLongLastingCallsCancelable )
182 , m_pCloseable(pCloseable)
184 impl_init();
187 CloseableLifeTimeManager::~CloseableLifeTimeManager()
191 sal_Bool CloseableLifeTimeManager
192 ::impl_isDisposedOrClosed()
194 if( impl_isDisposed() )
195 return sal_True;
197 if( m_bClosed )
199 OSL_ENSURE( sal_False, "This object is already closed" );
200 return sal_True;
202 return sal_False;
205 sal_Bool CloseableLifeTimeManager
206 ::g_close_startTryClose(sal_Bool bDeliverOwnership)
207 throw ( uno::Exception )
209 //no mutex is allowed to be acquired
211 osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex );
213 //Mutex needs to be acquired exactly ones; will be released inbetween
214 if( !impl_canStartApiCall() )
215 return sal_False;
216 //mutex is acquired
218 //not closed already -> we try to close again
219 m_bInTryClose = sal_True;
220 m_aEndTryClosingCondition.reset();
222 impl_registerApiCall(sal_False);
225 //------------------------------------------------
226 //no mutex is acquired
228 //only remove listener calls will be worked on until end of tryclose
229 //all other new calls will wait till end of try close // @todo? is that really ok
231 //?? still running calls have the freedom to finish their work without crash
235 uno::Reference< util::XCloseable > xCloseable =
236 uno::Reference< util::XCloseable >(m_pCloseable);;
237 if(xCloseable.is())
239 //--call queryClosing on all registered close listeners
240 ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer(
241 ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );;
242 if( pIC )
244 //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) );
245 lang::EventObject aEvent( xCloseable );
246 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
247 while( aIt.hasMoreElements() )
249 uno::Reference< util::XCloseListener > xCloseListener( aIt.next(), uno::UNO_QUERY );
250 if(xCloseListener.is())
251 xCloseListener->queryClosing( aEvent, bDeliverOwnership );
256 catch( uno::Exception& ex )
258 //no mutex is acquired
259 g_close_endTryClose(bDeliverOwnership, sal_False);
260 (void)(ex);
261 throw;
263 return sal_True;
266 void CloseableLifeTimeManager
267 ::g_close_endTryClose(sal_Bool bDeliverOwnership, sal_Bool /* bMyVeto */ )
269 //this method is called, if the try to close was not successfull
270 osl::Guard< osl::Mutex > aGuard( m_aAccessMutex );
271 impl_setOwnership( bDeliverOwnership, sal_False );
273 m_bInTryClose = sal_False;
274 m_aEndTryClosingCondition.set();
276 //Mutex needs to be acquired exactly ones
277 //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
278 impl_unregisterApiCall(sal_False);
281 sal_Bool CloseableLifeTimeManager
282 ::g_close_isNeedToCancelLongLastingCalls( sal_Bool bDeliverOwnership, util::CloseVetoException& ex )
283 throw ( util::CloseVetoException )
285 //this method is called when no closelistener has had a veto during queryclosing
286 //the method returns false, if nothing stands against closing anymore
287 //it returns true, if some longlasting calls are running, which might be cancelled
288 //it throws the given exception, if long calls are running but not cancelable
290 osl::Guard< osl::Mutex > aGuard( m_aAccessMutex );
291 //this count cannot grow after try of close has started, because we wait in all those methods for end of try closing
292 if( !m_nLongLastingCallCount )
293 return sal_False;
295 if(m_bLongLastingCallsCancelable)
296 return sal_True;
298 impl_setOwnership( bDeliverOwnership, sal_True );
300 m_bInTryClose = sal_False;
301 m_aEndTryClosingCondition.set();
303 //Mutex needs to be acquired exactly ones
304 //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
305 impl_unregisterApiCall(sal_False);
307 throw ex;
310 void CloseableLifeTimeManager
311 ::g_close_endTryClose_doClose()
313 //this method is called, if the try to close was successfull
314 osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex );
316 m_bInTryClose = sal_False;
317 m_aEndTryClosingCondition.set();
319 //Mutex needs to be acquired exactly ones
320 //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
321 impl_unregisterApiCall(sal_False);
322 impl_doClose();
325 void CloseableLifeTimeManager
326 ::impl_setOwnership( sal_Bool bDeliverOwnership, sal_Bool bMyVeto )
328 m_bOwnership = bDeliverOwnership && bMyVeto;
329 m_bOwnershipIsWellKnown = sal_True;
331 sal_Bool CloseableLifeTimeManager
332 ::impl_shouldCloseAtNextChance()
334 return m_bOwnership;
337 void CloseableLifeTimeManager
338 ::impl_apiCallCountReachedNull()
340 //Mutex needs to be acquired exactly ones
341 //mutex will be released inbetween in impl_doClose()
342 if( m_pCloseable && impl_shouldCloseAtNextChance() )
343 impl_doClose();
346 void CloseableLifeTimeManager
347 ::impl_doClose()
349 //Mutex needs to be acquired exactly ones before calling impl_doClose()
351 if(m_bClosed)
352 return; //behave as passive as possible, if disposed or closed already
353 if( m_bDisposed || m_bInDispose )
354 return; //behave as passive as possible, if disposed or closed already
356 //--------
357 m_bClosed = sal_True;
359 NegativeGuard< osl::Mutex > aNegativeGuard( m_aAccessMutex );
360 //mutex is not acquired, mutex will be reacquired at the end of this method automatically
362 uno::Reference< util::XCloseable > xCloseable=NULL;
365 xCloseable = uno::Reference< util::XCloseable >(m_pCloseable);;
366 if(xCloseable.is())
368 //--call notifyClosing on all registered close listeners
369 ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer(
370 ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );;
371 if( pIC )
373 //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) );
374 lang::EventObject aEvent( xCloseable );
375 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
376 while( aIt.hasMoreElements() )
377 (static_cast< util::XCloseListener*>(aIt.next()))->notifyClosing( aEvent );
381 catch( uno::Exception& ex )
383 ASSERT_EXCEPTION( ex );
386 if(xCloseable.is())
388 uno::Reference< lang::XComponent > xComponent =
389 uno::Reference< lang::XComponent >( xCloseable, uno::UNO_QUERY );
390 if(xComponent.is())
392 OSL_ENSURE( m_bClosed, "a not closed component will be disposed " );
393 xComponent->dispose();
396 //mutex will be reacquired in destructor of aNegativeGuard
399 sal_Bool CloseableLifeTimeManager
400 ::g_addCloseListener( const uno::Reference< util::XCloseListener > & xListener )
401 throw(uno::RuntimeException)
403 osl::Guard< osl::Mutex > aGuard( m_aAccessMutex );
404 //Mutex needs to be acquired exactly ones; will be released inbetween
405 if( !impl_canStartApiCall() )
406 return sal_False;
407 //mutex is acquired
409 m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< util::XCloseListener >*)0),xListener );
410 m_bOwnership = sal_False;
411 return sal_True;
414 sal_Bool CloseableLifeTimeManager
415 ::impl_canStartApiCall()
417 //Mutex needs to be acquired exactly ones before calling this method
418 //the mutex will be released inbetween and reacquired
420 if( impl_isDisposed() )
421 return sal_False; //behave passive if already disposed
422 if( m_bClosed )
423 return sal_False; //behave passive if closing is already done
425 //during try-close most calls need to wait for the decision
426 while( m_bInTryClose )
428 //if someone tries to close this object at the moment
429 //we need to wait for his end because the result of the preceding call
430 //is relevant for our behaviour here
432 m_aAccessMutex.release();
433 m_aEndTryClosingCondition.wait(); //@todo??? this may block??? try closing
434 m_aAccessMutex.acquire();
435 if( m_bDisposed || m_bInDispose || m_bClosed )
436 return sal_False; //return if closed already
438 //mutex is acquired
439 return sal_True;
442 //--------------------------
444 sal_Bool LifeTimeGuard
445 ::startApiCall(sal_Bool bLongLastingCall)
447 //Mutex needs to be acquired exactly ones; will be released inbetween
448 //mutex is requiered due to constructor of LifeTimeGuard
450 OSL_ENSURE( !m_bCallRegistered, "this method is only allowed ones" );
451 if(m_bCallRegistered)
452 return sal_False;
454 //Mutex needs to be acquired exactly ones; will be released inbetween
455 if( !m_rManager.impl_canStartApiCall() )
456 return sal_False;
457 //mutex is acquired
459 m_bCallRegistered = sal_True;
460 m_bLongLastingCallRegistered = bLongLastingCall;
461 m_rManager.impl_registerApiCall(bLongLastingCall);
462 return sal_True;
465 LifeTimeGuard::~LifeTimeGuard()
469 //do acquire the mutex if it was cleared before
470 osl::MutexGuard g(m_rManager.m_aAccessMutex);
471 if(m_bCallRegistered)
473 //Mutex needs to be acquired exactly ones
474 //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
475 m_rManager.impl_unregisterApiCall(m_bLongLastingCallRegistered);
478 catch( uno::Exception& ex )
480 //@todo ? allow a uno::RuntimeException from dispose to travel through??
481 ex.Context.is(); //to avoid compilation warnings
486 the XCloseable::close method has to be implemented in the following way:
487 ::close
489 //hold no mutex
491 if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) )
492 return;
493 //no mutex is acquired
495 // At the end of this method may we must dispose ourself ...
496 // and may nobody from outside hold a reference to us ...
497 // then it's a good idea to do that by ourself.
498 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
500 //the listeners have had no veto
501 //check wether we self can close
503 util::CloseVetoException aVetoException = util::CloseVetoException(
504 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
505 "the model itself could not be closed" ) )
506 , static_cast< ::cppu::OWeakObject* >(this));
508 if( m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException ) )
510 ////you can empty this block, if you never start longlasting calls or
511 ////if your longlasting calls are per default not cancelable (check how you have constructed your LifeTimeManager)
513 sal_Bool bLongLastingCallsAreCanceled = sal_False;
516 //try to cancel running longlasting calls
517 //// @todo
519 catch( uno::Exception& ex )
521 //// @todo
522 //do not throw anything here!! (without endTryClose)
524 //if not successful canceled
525 if(!bLongLastingCallsAreCanceled)
527 m_aLifeTimeManager.g_close_endTryClose( bDeliverOwnership, sal_True );
528 throw aVetoException;
533 m_aLifeTimeManager.g_close_endTryClose_doClose();
537 }//end namespace apphelper