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