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