1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski #ifndef _LIFETIME_HXX 24*b1cdbd2cSJim Jagielski #define _LIFETIME_HXX 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski #include <osl/mutex.hxx> 27*b1cdbd2cSJim Jagielski #include <osl/conditn.hxx> 28*b1cdbd2cSJim Jagielski #ifndef _COM_SUN_STAR_UNO_EXCEPTION_HDL_ 29*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/Exception.hdl> 30*b1cdbd2cSJim Jagielski #endif 31*b1cdbd2cSJim Jagielski #include <cppuhelper/interfacecontainer.hxx> 32*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XCloseListener.hpp> 33*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XCloseable.hpp> 34*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XComponent.hpp> 35*b1cdbd2cSJim Jagielski #include <cppuhelper/weakref.hxx> 36*b1cdbd2cSJim Jagielski #include "charttoolsdllapi.hxx" 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski namespace apphelper 39*b1cdbd2cSJim Jagielski { 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski class LifeTimeGuard; 42*b1cdbd2cSJim Jagielski class LifeTimeManager 43*b1cdbd2cSJim Jagielski { 44*b1cdbd2cSJim Jagielski friend class LifeTimeGuard; 45*b1cdbd2cSJim Jagielski protected: 46*b1cdbd2cSJim Jagielski mutable ::osl::Mutex m_aAccessMutex; 47*b1cdbd2cSJim Jagielski public: 48*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS LifeTimeManager( ::com::sun::star::lang::XComponent* pComponent, sal_Bool bLongLastingCallsCancelable = sal_False ); 49*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS virtual ~LifeTimeManager(); 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS bool impl_isDisposed( bool bAssert=true ); 52*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS sal_Bool dispose() throw(::com::sun::star::uno::RuntimeException); 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski public: 55*b1cdbd2cSJim Jagielski ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; 56*b1cdbd2cSJim Jagielski 57*b1cdbd2cSJim Jagielski protected: 58*b1cdbd2cSJim Jagielski virtual sal_Bool impl_canStartApiCall(); impl_apiCallCountReachedNull()59*b1cdbd2cSJim Jagielski virtual void impl_apiCallCountReachedNull(){} 60*b1cdbd2cSJim Jagielski 61*b1cdbd2cSJim Jagielski void impl_registerApiCall(sal_Bool bLongLastingCall); 62*b1cdbd2cSJim Jagielski void impl_unregisterApiCall(sal_Bool bLongLastingCall); 63*b1cdbd2cSJim Jagielski 64*b1cdbd2cSJim Jagielski void impl_init(); 65*b1cdbd2cSJim Jagielski 66*b1cdbd2cSJim Jagielski protected: 67*b1cdbd2cSJim Jagielski ::com::sun::star::lang::XComponent* m_pComponent; 68*b1cdbd2cSJim Jagielski 69*b1cdbd2cSJim Jagielski ::osl::Condition m_aNoAccessCountCondition; 70*b1cdbd2cSJim Jagielski sal_Int32 volatile m_nAccessCount; 71*b1cdbd2cSJim Jagielski 72*b1cdbd2cSJim Jagielski sal_Bool volatile m_bDisposed; 73*b1cdbd2cSJim Jagielski sal_Bool volatile m_bInDispose; 74*b1cdbd2cSJim Jagielski 75*b1cdbd2cSJim Jagielski // 76*b1cdbd2cSJim Jagielski sal_Bool m_bLongLastingCallsCancelable; 77*b1cdbd2cSJim Jagielski ::osl::Condition m_aNoLongLastingCallCountCondition; 78*b1cdbd2cSJim Jagielski sal_Int32 volatile m_nLongLastingCallCount; 79*b1cdbd2cSJim Jagielski }; 80*b1cdbd2cSJim Jagielski 81*b1cdbd2cSJim Jagielski class CloseableLifeTimeManager : public LifeTimeManager 82*b1cdbd2cSJim Jagielski { 83*b1cdbd2cSJim Jagielski protected: 84*b1cdbd2cSJim Jagielski ::com::sun::star::util::XCloseable* m_pCloseable; 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielski ::osl::Condition m_aEndTryClosingCondition; 87*b1cdbd2cSJim Jagielski sal_Bool volatile m_bClosed; 88*b1cdbd2cSJim Jagielski sal_Bool volatile m_bInTryClose; 89*b1cdbd2cSJim Jagielski //the ownership between model and controller is not clear at first 90*b1cdbd2cSJim Jagielski //each controller might consider him as owner of the model first 91*b1cdbd2cSJim Jagielski //at start the model is not considered as owner of itself 92*b1cdbd2cSJim Jagielski sal_Bool volatile m_bOwnership; 93*b1cdbd2cSJim Jagielski //with a XCloseable::close call and during XCloseListener::queryClosing 94*b1cdbd2cSJim Jagielski //the ownership can be regulated more explicit, 95*b1cdbd2cSJim Jagielski //if so the ownership is considered to be well known 96*b1cdbd2cSJim Jagielski sal_Bool volatile m_bOwnershipIsWellKnown; 97*b1cdbd2cSJim Jagielski 98*b1cdbd2cSJim Jagielski public: 99*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS CloseableLifeTimeManager( ::com::sun::star::util::XCloseable* pCloseable 100*b1cdbd2cSJim Jagielski , ::com::sun::star::lang::XComponent* pComponent 101*b1cdbd2cSJim Jagielski , sal_Bool bLongLastingCallsCancelable = sal_False ); 102*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS virtual ~CloseableLifeTimeManager(); 103*b1cdbd2cSJim Jagielski 104*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS bool impl_isDisposedOrClosed( bool bAssert=true ); 105*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS sal_Bool g_close_startTryClose(sal_Bool bDeliverOwnership) 106*b1cdbd2cSJim Jagielski throw ( ::com::sun::star::uno::Exception ); 107*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS sal_Bool g_close_isNeedToCancelLongLastingCalls( sal_Bool bDeliverOwnership, ::com::sun::star::util::CloseVetoException& ex ) 108*b1cdbd2cSJim Jagielski throw ( ::com::sun::star::util::CloseVetoException ); 109*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS void g_close_endTryClose(sal_Bool bDeliverOwnership, sal_Bool bMyVeto ); 110*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS void g_close_endTryClose_doClose(); 111*b1cdbd2cSJim Jagielski OOO_DLLPUBLIC_CHARTTOOLS sal_Bool g_addCloseListener( const ::com::sun::star::uno::Reference< 112*b1cdbd2cSJim Jagielski ::com::sun::star::util::XCloseListener > & xListener ) 113*b1cdbd2cSJim Jagielski throw(::com::sun::star::uno::RuntimeException); 114*b1cdbd2cSJim Jagielski 115*b1cdbd2cSJim Jagielski protected: 116*b1cdbd2cSJim Jagielski virtual sal_Bool impl_canStartApiCall(); 117*b1cdbd2cSJim Jagielski virtual void impl_apiCallCountReachedNull(); 118*b1cdbd2cSJim Jagielski 119*b1cdbd2cSJim Jagielski void impl_setOwnership( sal_Bool bDeliverOwnership, sal_Bool bMyVeto ); 120*b1cdbd2cSJim Jagielski sal_Bool impl_shouldCloseAtNextChance(); 121*b1cdbd2cSJim Jagielski void impl_doClose(); 122*b1cdbd2cSJim Jagielski impl_init()123*b1cdbd2cSJim Jagielski void impl_init() 124*b1cdbd2cSJim Jagielski { 125*b1cdbd2cSJim Jagielski m_bClosed = sal_False; 126*b1cdbd2cSJim Jagielski m_bInTryClose = sal_False; 127*b1cdbd2cSJim Jagielski m_bOwnership = sal_False; 128*b1cdbd2cSJim Jagielski m_bOwnershipIsWellKnown = sal_False; 129*b1cdbd2cSJim Jagielski m_aEndTryClosingCondition.set(); 130*b1cdbd2cSJim Jagielski } 131*b1cdbd2cSJim Jagielski }; 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski //----------------------------------------------------------------- 134*b1cdbd2cSJim Jagielski /* 135*b1cdbd2cSJim Jagielski Use this Guard in your apicalls to protect access on resources 136*b1cdbd2cSJim Jagielski which will be released in dispose. 137*b1cdbd2cSJim Jagielski It's guarantied, that the release of resources only starts if your 138*b1cdbd2cSJim Jagielski guarded call has finished. 139*b1cdbd2cSJim Jagielski ! It's only partly guaranteed that this resources will not change during the call. 140*b1cdbd2cSJim Jagielski See the example for details. 141*b1cdbd2cSJim Jagielski 142*b1cdbd2cSJim Jagielski This class is to be used as described in the example. 143*b1cdbd2cSJim Jagielski 144*b1cdbd2cSJim Jagielski If this guard is used in all api calls of an XCloseable object 145*b1cdbd2cSJim Jagielski it's guarantied, that the closeable will close itself after finishing the last call 146*b1cdbd2cSJim Jagielski if it should do so. 147*b1cdbd2cSJim Jagielski 148*b1cdbd2cSJim Jagielski ::ApiCall 149*b1cdbd2cSJim Jagielski { 150*b1cdbd2cSJim Jagielski //hold no mutex!!! 151*b1cdbd2cSJim Jagielski LifeTimeGuard aLifeTimeGuard(m_aLifeTimeManager); 152*b1cdbd2cSJim Jagielski 153*b1cdbd2cSJim Jagielski //mutex is acquired; call is not registered 154*b1cdbd2cSJim Jagielski 155*b1cdbd2cSJim Jagielski if(!aLifeTimeGuard.startApiCall()) 156*b1cdbd2cSJim Jagielski return ; //behave as passive as possible, if disposed or closed 157*b1cdbd2cSJim Jagielski 158*b1cdbd2cSJim Jagielski //mutex is acquired, call is registered 159*b1cdbd2cSJim Jagielski { 160*b1cdbd2cSJim Jagielski //you might access some private members here 161*b1cdbd2cSJim Jagielski //but than you need to protect access to these members always like this 162*b1cdbd2cSJim Jagielski //never call to the outside here 163*b1cdbd2cSJim Jagielski } 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski aLifeTimeGuard.clear(); //!!! 166*b1cdbd2cSJim Jagielski 167*b1cdbd2cSJim Jagielski //Mutex is released, the running call is still registered 168*b1cdbd2cSJim Jagielski //this call will finish before the 'release-section' in dispose is allowed to start 169*b1cdbd2cSJim Jagielski 170*b1cdbd2cSJim Jagielski { 171*b1cdbd2cSJim Jagielski //you might access some private members here guarded with your own mutex 172*b1cdbd2cSJim Jagielski //but release your mutex at the end of this block 173*b1cdbd2cSJim Jagielski } 174*b1cdbd2cSJim Jagielski 175*b1cdbd2cSJim Jagielski //you can call to the outside (without holding the mutex) without becoming disposed 176*b1cdbd2cSJim Jagielski 177*b1cdbd2cSJim Jagielski //End of method -> ~LifeTimeGuard 178*b1cdbd2cSJim Jagielski //-> call is unregistered 179*b1cdbd2cSJim Jagielski //-> this object might be disposed now 180*b1cdbd2cSJim Jagielski } 181*b1cdbd2cSJim Jagielski 182*b1cdbd2cSJim Jagielski your XComponent::dispose method has to be implemented in the following way: 183*b1cdbd2cSJim Jagielski 184*b1cdbd2cSJim Jagielski ::dispose() 185*b1cdbd2cSJim Jagielski { 186*b1cdbd2cSJim Jagielski //hold no mutex!!! 187*b1cdbd2cSJim Jagielski if( !m_aLifeTimeManager.dispose() ) 188*b1cdbd2cSJim Jagielski return; 189*b1cdbd2cSJim Jagielski 190*b1cdbd2cSJim Jagielski //--release all resources and references 191*b1cdbd2cSJim Jagielski //... 192*b1cdbd2cSJim Jagielski } 193*b1cdbd2cSJim Jagielski 194*b1cdbd2cSJim Jagielski */ 195*b1cdbd2cSJim Jagielski //----------------------------------------------------------------- 196*b1cdbd2cSJim Jagielski 197*b1cdbd2cSJim Jagielski class OOO_DLLPUBLIC_CHARTTOOLS LifeTimeGuard 198*b1cdbd2cSJim Jagielski { 199*b1cdbd2cSJim Jagielski 200*b1cdbd2cSJim Jagielski public: LifeTimeGuard(LifeTimeManager & rManager)201*b1cdbd2cSJim Jagielski LifeTimeGuard( LifeTimeManager& rManager ) 202*b1cdbd2cSJim Jagielski : m_guard( rManager.m_aAccessMutex ) 203*b1cdbd2cSJim Jagielski , m_rManager(rManager) 204*b1cdbd2cSJim Jagielski , m_bCallRegistered(sal_False) 205*b1cdbd2cSJim Jagielski , m_bLongLastingCallRegistered(sal_False) 206*b1cdbd2cSJim Jagielski { 207*b1cdbd2cSJim Jagielski 208*b1cdbd2cSJim Jagielski } 209*b1cdbd2cSJim Jagielski sal_Bool startApiCall(sal_Bool bLongLastingCall=sal_False); 210*b1cdbd2cSJim Jagielski ~LifeTimeGuard(); clear()211*b1cdbd2cSJim Jagielski void clear() { m_guard.clear(); } 212*b1cdbd2cSJim Jagielski 213*b1cdbd2cSJim Jagielski private: 214*b1cdbd2cSJim Jagielski osl::ClearableMutexGuard m_guard; 215*b1cdbd2cSJim Jagielski LifeTimeManager& m_rManager; 216*b1cdbd2cSJim Jagielski sal_Bool m_bCallRegistered; 217*b1cdbd2cSJim Jagielski sal_Bool m_bLongLastingCallRegistered; 218*b1cdbd2cSJim Jagielski 219*b1cdbd2cSJim Jagielski private: 220*b1cdbd2cSJim Jagielski // these make no sense 221*b1cdbd2cSJim Jagielski LifeTimeGuard( ::osl::Mutex& rMutex ); 222*b1cdbd2cSJim Jagielski LifeTimeGuard( const LifeTimeGuard& ); 223*b1cdbd2cSJim Jagielski LifeTimeGuard& operator= ( const LifeTimeGuard& ); 224*b1cdbd2cSJim Jagielski }; 225*b1cdbd2cSJim Jagielski 226*b1cdbd2cSJim Jagielski 227*b1cdbd2cSJim Jagielski template<class T> 228*b1cdbd2cSJim Jagielski class NegativeGuard 229*b1cdbd2cSJim Jagielski { 230*b1cdbd2cSJim Jagielski protected: 231*b1cdbd2cSJim Jagielski T * m_pT; 232*b1cdbd2cSJim Jagielski public: 233*b1cdbd2cSJim Jagielski NegativeGuard(T * pT)234*b1cdbd2cSJim Jagielski NegativeGuard(T * pT) : m_pT(pT) 235*b1cdbd2cSJim Jagielski { 236*b1cdbd2cSJim Jagielski m_pT->release(); 237*b1cdbd2cSJim Jagielski } 238*b1cdbd2cSJim Jagielski NegativeGuard(T & t)239*b1cdbd2cSJim Jagielski NegativeGuard(T & t) : m_pT(&t) 240*b1cdbd2cSJim Jagielski { 241*b1cdbd2cSJim Jagielski m_pT->release(); 242*b1cdbd2cSJim Jagielski } 243*b1cdbd2cSJim Jagielski ~NegativeGuard()244*b1cdbd2cSJim Jagielski ~NegativeGuard() 245*b1cdbd2cSJim Jagielski { 246*b1cdbd2cSJim Jagielski m_pT->acquire(); 247*b1cdbd2cSJim Jagielski } 248*b1cdbd2cSJim Jagielski }; 249*b1cdbd2cSJim Jagielski 250*b1cdbd2cSJim Jagielski }//end namespace apphelper 251*b1cdbd2cSJim Jagielski #endif 252