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