1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_chart2.hxx" 30*cdf0e10cSrcweir #include "LifeTime.hxx" 31*cdf0e10cSrcweir #include "macros.hxx" 32*cdf0e10cSrcweir #include <osl/diagnose.h> 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #include <com/sun/star/util/XModifyListener.hpp> 35*cdf0e10cSrcweir #include <com/sun/star/util/XCloseListener.hpp> 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir using namespace ::com::sun::star; 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir namespace apphelper 40*cdf0e10cSrcweir { 41*cdf0e10cSrcweir //-------------------------- 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir LifeTimeManager::LifeTimeManager( lang::XComponent* pComponent, sal_Bool bLongLastingCallsCancelable ) 44*cdf0e10cSrcweir : m_aListenerContainer( m_aAccessMutex ) 45*cdf0e10cSrcweir , m_pComponent(pComponent) 46*cdf0e10cSrcweir , m_bLongLastingCallsCancelable(bLongLastingCallsCancelable) 47*cdf0e10cSrcweir { 48*cdf0e10cSrcweir impl_init(); 49*cdf0e10cSrcweir } 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir void LifeTimeManager::impl_init() 52*cdf0e10cSrcweir { 53*cdf0e10cSrcweir m_bDisposed = sal_False; 54*cdf0e10cSrcweir m_bInDispose = sal_False; 55*cdf0e10cSrcweir m_nAccessCount = 0; 56*cdf0e10cSrcweir m_nLongLastingCallCount = 0; 57*cdf0e10cSrcweir m_aNoAccessCountCondition.set(); 58*cdf0e10cSrcweir m_aNoLongLastingCallCountCondition.set(); 59*cdf0e10cSrcweir } 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir LifeTimeManager::~LifeTimeManager() 62*cdf0e10cSrcweir { 63*cdf0e10cSrcweir } 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir bool LifeTimeManager::impl_isDisposed( bool bAssert ) 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir if( m_bDisposed || m_bInDispose ) 68*cdf0e10cSrcweir { 69*cdf0e10cSrcweir if( bAssert ) 70*cdf0e10cSrcweir { 71*cdf0e10cSrcweir OSL_ENSURE( sal_False, "This component is already disposed " ); 72*cdf0e10cSrcweir (void)(bAssert); 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir return sal_True; 75*cdf0e10cSrcweir } 76*cdf0e10cSrcweir return sal_False; 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir sal_Bool LifeTimeManager 79*cdf0e10cSrcweir ::impl_canStartApiCall() 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir if( impl_isDisposed() ) 82*cdf0e10cSrcweir return sal_False; //behave passive if already disposed 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir //mutex is acquired 85*cdf0e10cSrcweir return sal_True; 86*cdf0e10cSrcweir } 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir void LifeTimeManager 89*cdf0e10cSrcweir ::impl_registerApiCall(sal_Bool bLongLastingCall) 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir //only allowed if not disposed 92*cdf0e10cSrcweir //do not acquire the mutex here because it will be acquired already 93*cdf0e10cSrcweir m_nAccessCount++; 94*cdf0e10cSrcweir if(m_nAccessCount==1) 95*cdf0e10cSrcweir //@todo? is it ok to wake some threads here while we have acquired the mutex? 96*cdf0e10cSrcweir m_aNoAccessCountCondition.reset(); 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir if(bLongLastingCall) 99*cdf0e10cSrcweir m_nLongLastingCallCount++; 100*cdf0e10cSrcweir if(m_nLongLastingCallCount==1) 101*cdf0e10cSrcweir m_aNoLongLastingCallCountCondition.reset(); 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir void LifeTimeManager 104*cdf0e10cSrcweir ::impl_unregisterApiCall(sal_Bool bLongLastingCall) 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 107*cdf0e10cSrcweir //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir OSL_ENSURE( m_nAccessCount>0, "access count mismatch" ); 110*cdf0e10cSrcweir m_nAccessCount--; 111*cdf0e10cSrcweir if(bLongLastingCall) 112*cdf0e10cSrcweir m_nLongLastingCallCount--; 113*cdf0e10cSrcweir if( m_nLongLastingCallCount==0 ) 114*cdf0e10cSrcweir { 115*cdf0e10cSrcweir m_aNoLongLastingCallCountCondition.set(); 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir if( m_nAccessCount== 0) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir m_aNoAccessCountCondition.set(); 120*cdf0e10cSrcweir impl_apiCallCountReachedNull(); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir } 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir sal_Bool LifeTimeManager 126*cdf0e10cSrcweir ::dispose() throw(uno::RuntimeException) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir //hold no mutex 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir if( m_bDisposed || m_bInDispose ) 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir OSL_TRACE( "This component is already disposed " ); 135*cdf0e10cSrcweir return sal_False; //behave passive if already disposed 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir m_bInDispose = true; 139*cdf0e10cSrcweir //adding any listener is not allowed anymore 140*cdf0e10cSrcweir //new calls will not be accepted 141*cdf0e10cSrcweir //still running calls have the freedom to finish their work without crash 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir //no mutex is acquired 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir //--do the disposing of listeners after calling this method 146*cdf0e10cSrcweir { 147*cdf0e10cSrcweir uno::Reference< lang::XComponent > xComponent = 148*cdf0e10cSrcweir uno::Reference< lang::XComponent >(m_pComponent);; 149*cdf0e10cSrcweir if(xComponent.is()) 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir // notify XCLoseListeners 152*cdf0e10cSrcweir lang::EventObject aEvent( xComponent ); 153*cdf0e10cSrcweir m_aListenerContainer.disposeAndClear( aEvent ); 154*cdf0e10cSrcweir } 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir //no mutex is acquired 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir osl::ClearableGuard< osl::Mutex > aGuard( m_aAccessMutex ); 160*cdf0e10cSrcweir OSL_ENSURE( !m_bDisposed, "dispose was called already" ); 161*cdf0e10cSrcweir m_bDisposed = sal_True; 162*cdf0e10cSrcweir aGuard.clear(); 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir //no mutex is acquired 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir //wait until all still running calls have finished 167*cdf0e10cSrcweir //the accessCount cannot grow anymore, because all calls will return after checking m_bDisposed 168*cdf0e10cSrcweir m_aNoAccessCountCondition.wait(); 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir //we are the only ones working on our data now 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir return sal_True; 173*cdf0e10cSrcweir //--release all resources and references after calling this method successful 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir //----------------------------------------------------------------- 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir CloseableLifeTimeManager::CloseableLifeTimeManager( ::com::sun::star::util::XCloseable* pCloseable 179*cdf0e10cSrcweir , ::com::sun::star::lang::XComponent* pComponent 180*cdf0e10cSrcweir , sal_Bool bLongLastingCallsCancelable ) 181*cdf0e10cSrcweir : LifeTimeManager( pComponent, bLongLastingCallsCancelable ) 182*cdf0e10cSrcweir , m_pCloseable(pCloseable) 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir impl_init(); 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir CloseableLifeTimeManager::~CloseableLifeTimeManager() 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir bool CloseableLifeTimeManager::impl_isDisposedOrClosed( bool bAssert ) 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir if( impl_isDisposed( bAssert ) ) 194*cdf0e10cSrcweir return sal_True; 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir if( m_bClosed ) 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir if( bAssert ) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir OSL_ENSURE( sal_False, "This object is already closed" ); 201*cdf0e10cSrcweir (void)(bAssert);//avoid warnings 202*cdf0e10cSrcweir } 203*cdf0e10cSrcweir return sal_True; 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir return sal_False; 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir sal_Bool CloseableLifeTimeManager 209*cdf0e10cSrcweir ::g_close_startTryClose(sal_Bool bDeliverOwnership) 210*cdf0e10cSrcweir throw ( uno::Exception ) 211*cdf0e10cSrcweir { 212*cdf0e10cSrcweir //no mutex is allowed to be acquired 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex ); 215*cdf0e10cSrcweir if( impl_isDisposedOrClosed(false) ) 216*cdf0e10cSrcweir return sal_False; 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones; will be released inbetween 219*cdf0e10cSrcweir if( !impl_canStartApiCall() ) 220*cdf0e10cSrcweir return sal_False; 221*cdf0e10cSrcweir //mutex is acquired 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir //not closed already -> we try to close again 224*cdf0e10cSrcweir m_bInTryClose = sal_True; 225*cdf0e10cSrcweir m_aEndTryClosingCondition.reset(); 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir impl_registerApiCall(sal_False); 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir //------------------------------------------------ 231*cdf0e10cSrcweir //no mutex is acquired 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir //only remove listener calls will be worked on until end of tryclose 234*cdf0e10cSrcweir //all other new calls will wait till end of try close // @todo? is that really ok 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir //?? still running calls have the freedom to finish their work without crash 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir try 239*cdf0e10cSrcweir { 240*cdf0e10cSrcweir uno::Reference< util::XCloseable > xCloseable = 241*cdf0e10cSrcweir uno::Reference< util::XCloseable >(m_pCloseable);; 242*cdf0e10cSrcweir if(xCloseable.is()) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir //--call queryClosing on all registered close listeners 245*cdf0e10cSrcweir ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( 246*cdf0e10cSrcweir ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );; 247*cdf0e10cSrcweir if( pIC ) 248*cdf0e10cSrcweir { 249*cdf0e10cSrcweir //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) ); 250*cdf0e10cSrcweir lang::EventObject aEvent( xCloseable ); 251*cdf0e10cSrcweir ::cppu::OInterfaceIteratorHelper aIt( *pIC ); 252*cdf0e10cSrcweir while( aIt.hasMoreElements() ) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir uno::Reference< util::XCloseListener > xCloseListener( aIt.next(), uno::UNO_QUERY ); 255*cdf0e10cSrcweir if(xCloseListener.is()) 256*cdf0e10cSrcweir xCloseListener->queryClosing( aEvent, bDeliverOwnership ); 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir catch( uno::Exception& ex ) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir //no mutex is acquired 264*cdf0e10cSrcweir g_close_endTryClose(bDeliverOwnership, sal_False); 265*cdf0e10cSrcweir (void)(ex); 266*cdf0e10cSrcweir throw; 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir return sal_True; 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir void CloseableLifeTimeManager 272*cdf0e10cSrcweir ::g_close_endTryClose(sal_Bool bDeliverOwnership, sal_Bool /* bMyVeto */ ) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir //this method is called, if the try to close was not successfull 275*cdf0e10cSrcweir osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); 276*cdf0e10cSrcweir impl_setOwnership( bDeliverOwnership, sal_False ); 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir m_bInTryClose = sal_False; 279*cdf0e10cSrcweir m_aEndTryClosingCondition.set(); 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 282*cdf0e10cSrcweir //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() 283*cdf0e10cSrcweir impl_unregisterApiCall(sal_False); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir sal_Bool CloseableLifeTimeManager 287*cdf0e10cSrcweir ::g_close_isNeedToCancelLongLastingCalls( sal_Bool bDeliverOwnership, util::CloseVetoException& ex ) 288*cdf0e10cSrcweir throw ( util::CloseVetoException ) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir //this method is called when no closelistener has had a veto during queryclosing 291*cdf0e10cSrcweir //the method returns false, if nothing stands against closing anymore 292*cdf0e10cSrcweir //it returns true, if some longlasting calls are running, which might be cancelled 293*cdf0e10cSrcweir //it throws the given exception, if long calls are running but not cancelable 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); 296*cdf0e10cSrcweir //this count cannot grow after try of close has started, because we wait in all those methods for end of try closing 297*cdf0e10cSrcweir if( !m_nLongLastingCallCount ) 298*cdf0e10cSrcweir return sal_False; 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir if(m_bLongLastingCallsCancelable) 301*cdf0e10cSrcweir return sal_True; 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir impl_setOwnership( bDeliverOwnership, sal_True ); 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir m_bInTryClose = sal_False; 306*cdf0e10cSrcweir m_aEndTryClosingCondition.set(); 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 309*cdf0e10cSrcweir //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() 310*cdf0e10cSrcweir impl_unregisterApiCall(sal_False); 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir throw ex; 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir void CloseableLifeTimeManager 316*cdf0e10cSrcweir ::g_close_endTryClose_doClose() 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir //this method is called, if the try to close was successfull 319*cdf0e10cSrcweir osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex ); 320*cdf0e10cSrcweir 321*cdf0e10cSrcweir m_bInTryClose = sal_False; 322*cdf0e10cSrcweir m_aEndTryClosingCondition.set(); 323*cdf0e10cSrcweir 324*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 325*cdf0e10cSrcweir //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() 326*cdf0e10cSrcweir impl_unregisterApiCall(sal_False); 327*cdf0e10cSrcweir impl_doClose(); 328*cdf0e10cSrcweir } 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir void CloseableLifeTimeManager 331*cdf0e10cSrcweir ::impl_setOwnership( sal_Bool bDeliverOwnership, sal_Bool bMyVeto ) 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir m_bOwnership = bDeliverOwnership && bMyVeto; 334*cdf0e10cSrcweir m_bOwnershipIsWellKnown = sal_True; 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir sal_Bool CloseableLifeTimeManager 337*cdf0e10cSrcweir ::impl_shouldCloseAtNextChance() 338*cdf0e10cSrcweir { 339*cdf0e10cSrcweir return m_bOwnership; 340*cdf0e10cSrcweir } 341*cdf0e10cSrcweir 342*cdf0e10cSrcweir void CloseableLifeTimeManager 343*cdf0e10cSrcweir ::impl_apiCallCountReachedNull() 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 346*cdf0e10cSrcweir //mutex will be released inbetween in impl_doClose() 347*cdf0e10cSrcweir if( m_pCloseable && impl_shouldCloseAtNextChance() ) 348*cdf0e10cSrcweir impl_doClose(); 349*cdf0e10cSrcweir } 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir void CloseableLifeTimeManager 352*cdf0e10cSrcweir ::impl_doClose() 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones before calling impl_doClose() 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir if(m_bClosed) 357*cdf0e10cSrcweir return; //behave as passive as possible, if disposed or closed already 358*cdf0e10cSrcweir if( m_bDisposed || m_bInDispose ) 359*cdf0e10cSrcweir return; //behave as passive as possible, if disposed or closed already 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir //-------- 362*cdf0e10cSrcweir m_bClosed = sal_True; 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir NegativeGuard< osl::Mutex > aNegativeGuard( m_aAccessMutex ); 365*cdf0e10cSrcweir //mutex is not acquired, mutex will be reacquired at the end of this method automatically 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir uno::Reference< util::XCloseable > xCloseable=NULL; 368*cdf0e10cSrcweir try 369*cdf0e10cSrcweir { 370*cdf0e10cSrcweir xCloseable = uno::Reference< util::XCloseable >(m_pCloseable);; 371*cdf0e10cSrcweir if(xCloseable.is()) 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir //--call notifyClosing on all registered close listeners 374*cdf0e10cSrcweir ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( 375*cdf0e10cSrcweir ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );; 376*cdf0e10cSrcweir if( pIC ) 377*cdf0e10cSrcweir { 378*cdf0e10cSrcweir //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) ); 379*cdf0e10cSrcweir lang::EventObject aEvent( xCloseable ); 380*cdf0e10cSrcweir ::cppu::OInterfaceIteratorHelper aIt( *pIC ); 381*cdf0e10cSrcweir while( aIt.hasMoreElements() ) 382*cdf0e10cSrcweir { 383*cdf0e10cSrcweir uno::Reference< util::XCloseListener > xListener( aIt.next(), uno::UNO_QUERY ); 384*cdf0e10cSrcweir if( xListener.is() ) 385*cdf0e10cSrcweir xListener->notifyClosing( aEvent ); 386*cdf0e10cSrcweir } 387*cdf0e10cSrcweir } 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir catch( uno::Exception& ex ) 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir ASSERT_EXCEPTION( ex ); 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir if(xCloseable.is()) 396*cdf0e10cSrcweir { 397*cdf0e10cSrcweir uno::Reference< lang::XComponent > xComponent = 398*cdf0e10cSrcweir uno::Reference< lang::XComponent >( xCloseable, uno::UNO_QUERY ); 399*cdf0e10cSrcweir if(xComponent.is()) 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir OSL_ENSURE( m_bClosed, "a not closed component will be disposed " ); 402*cdf0e10cSrcweir xComponent->dispose(); 403*cdf0e10cSrcweir } 404*cdf0e10cSrcweir } 405*cdf0e10cSrcweir //mutex will be reacquired in destructor of aNegativeGuard 406*cdf0e10cSrcweir } 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir sal_Bool CloseableLifeTimeManager 409*cdf0e10cSrcweir ::g_addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) 410*cdf0e10cSrcweir throw(uno::RuntimeException) 411*cdf0e10cSrcweir { 412*cdf0e10cSrcweir osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); 413*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones; will be released inbetween 414*cdf0e10cSrcweir if( !impl_canStartApiCall() ) 415*cdf0e10cSrcweir return sal_False; 416*cdf0e10cSrcweir //mutex is acquired 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< util::XCloseListener >*)0),xListener ); 419*cdf0e10cSrcweir m_bOwnership = sal_False; 420*cdf0e10cSrcweir return sal_True; 421*cdf0e10cSrcweir } 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir sal_Bool CloseableLifeTimeManager 424*cdf0e10cSrcweir ::impl_canStartApiCall() 425*cdf0e10cSrcweir { 426*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones before calling this method 427*cdf0e10cSrcweir //the mutex will be released inbetween and reacquired 428*cdf0e10cSrcweir 429*cdf0e10cSrcweir if( impl_isDisposed() ) 430*cdf0e10cSrcweir return sal_False; //behave passive if already disposed 431*cdf0e10cSrcweir if( m_bClosed ) 432*cdf0e10cSrcweir return sal_False; //behave passive if closing is already done 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir //during try-close most calls need to wait for the decision 435*cdf0e10cSrcweir while( m_bInTryClose ) 436*cdf0e10cSrcweir { 437*cdf0e10cSrcweir //if someone tries to close this object at the moment 438*cdf0e10cSrcweir //we need to wait for his end because the result of the preceding call 439*cdf0e10cSrcweir //is relevant for our behaviour here 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir m_aAccessMutex.release(); 442*cdf0e10cSrcweir m_aEndTryClosingCondition.wait(); //@todo??? this may block??? try closing 443*cdf0e10cSrcweir m_aAccessMutex.acquire(); 444*cdf0e10cSrcweir if( m_bDisposed || m_bInDispose || m_bClosed ) 445*cdf0e10cSrcweir return sal_False; //return if closed already 446*cdf0e10cSrcweir } 447*cdf0e10cSrcweir //mutex is acquired 448*cdf0e10cSrcweir return sal_True; 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir //-------------------------- 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir sal_Bool LifeTimeGuard 454*cdf0e10cSrcweir ::startApiCall(sal_Bool bLongLastingCall) 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones; will be released inbetween 457*cdf0e10cSrcweir //mutex is requiered due to constructor of LifeTimeGuard 458*cdf0e10cSrcweir 459*cdf0e10cSrcweir OSL_ENSURE( !m_bCallRegistered, "this method is only allowed ones" ); 460*cdf0e10cSrcweir if(m_bCallRegistered) 461*cdf0e10cSrcweir return sal_False; 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones; will be released inbetween 464*cdf0e10cSrcweir if( !m_rManager.impl_canStartApiCall() ) 465*cdf0e10cSrcweir return sal_False; 466*cdf0e10cSrcweir //mutex is acquired 467*cdf0e10cSrcweir 468*cdf0e10cSrcweir m_bCallRegistered = sal_True; 469*cdf0e10cSrcweir m_bLongLastingCallRegistered = bLongLastingCall; 470*cdf0e10cSrcweir m_rManager.impl_registerApiCall(bLongLastingCall); 471*cdf0e10cSrcweir return sal_True; 472*cdf0e10cSrcweir } 473*cdf0e10cSrcweir 474*cdf0e10cSrcweir LifeTimeGuard::~LifeTimeGuard() 475*cdf0e10cSrcweir { 476*cdf0e10cSrcweir try 477*cdf0e10cSrcweir { 478*cdf0e10cSrcweir //do acquire the mutex if it was cleared before 479*cdf0e10cSrcweir osl::MutexGuard g(m_rManager.m_aAccessMutex); 480*cdf0e10cSrcweir if(m_bCallRegistered) 481*cdf0e10cSrcweir { 482*cdf0e10cSrcweir //Mutex needs to be acquired exactly ones 483*cdf0e10cSrcweir //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() 484*cdf0e10cSrcweir m_rManager.impl_unregisterApiCall(m_bLongLastingCallRegistered); 485*cdf0e10cSrcweir } 486*cdf0e10cSrcweir } 487*cdf0e10cSrcweir catch( uno::Exception& ex ) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir //@todo ? allow a uno::RuntimeException from dispose to travel through?? 490*cdf0e10cSrcweir ex.Context.is(); //to avoid compilation warnings 491*cdf0e10cSrcweir } 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir /* 495*cdf0e10cSrcweir the XCloseable::close method has to be implemented in the following way: 496*cdf0e10cSrcweir ::close 497*cdf0e10cSrcweir { 498*cdf0e10cSrcweir //hold no mutex 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) ) 501*cdf0e10cSrcweir return; 502*cdf0e10cSrcweir //no mutex is acquired 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir // At the end of this method may we must dispose ourself ... 505*cdf0e10cSrcweir // and may nobody from outside hold a reference to us ... 506*cdf0e10cSrcweir // then it's a good idea to do that by ourself. 507*cdf0e10cSrcweir uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) ); 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir //the listeners have had no veto 510*cdf0e10cSrcweir //check wether we self can close 511*cdf0e10cSrcweir { 512*cdf0e10cSrcweir util::CloseVetoException aVetoException = util::CloseVetoException( 513*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 514*cdf0e10cSrcweir "the model itself could not be closed" ) ) 515*cdf0e10cSrcweir , static_cast< ::cppu::OWeakObject* >(this)); 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir if( m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException ) ) 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir ////you can empty this block, if you never start longlasting calls or 520*cdf0e10cSrcweir ////if your longlasting calls are per default not cancelable (check how you have constructed your LifeTimeManager) 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir sal_Bool bLongLastingCallsAreCanceled = sal_False; 523*cdf0e10cSrcweir try 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir //try to cancel running longlasting calls 526*cdf0e10cSrcweir //// @todo 527*cdf0e10cSrcweir } 528*cdf0e10cSrcweir catch( uno::Exception& ex ) 529*cdf0e10cSrcweir { 530*cdf0e10cSrcweir //// @todo 531*cdf0e10cSrcweir //do not throw anything here!! (without endTryClose) 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir //if not successful canceled 534*cdf0e10cSrcweir if(!bLongLastingCallsAreCanceled) 535*cdf0e10cSrcweir { 536*cdf0e10cSrcweir m_aLifeTimeManager.g_close_endTryClose( bDeliverOwnership, sal_True ); 537*cdf0e10cSrcweir throw aVetoException; 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir m_aLifeTimeManager.g_close_endTryClose_doClose(); 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir */ 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir }//end namespace apphelper 547