xref: /aoo41x/main/chart2/source/tools/LifeTime.cxx (revision cde9e8dc)
1*cde9e8dcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*cde9e8dcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*cde9e8dcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*cde9e8dcSAndrew Rist  * distributed with this work for additional information
6*cde9e8dcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*cde9e8dcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*cde9e8dcSAndrew Rist  * "License"); you may not use this file except in compliance
9*cde9e8dcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*cde9e8dcSAndrew Rist  *
11*cde9e8dcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*cde9e8dcSAndrew Rist  *
13*cde9e8dcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*cde9e8dcSAndrew Rist  * software distributed under the License is distributed on an
15*cde9e8dcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*cde9e8dcSAndrew Rist  * KIND, either express or implied.  See the License for the
17*cde9e8dcSAndrew Rist  * specific language governing permissions and limitations
18*cde9e8dcSAndrew Rist  * under the License.
19*cde9e8dcSAndrew Rist  *
20*cde9e8dcSAndrew Rist  *************************************************************/
21*cde9e8dcSAndrew Rist 
22*cde9e8dcSAndrew 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 
LifeTimeManager(lang::XComponent * pComponent,sal_Bool bLongLastingCallsCancelable)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 
impl_init()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 
~LifeTimeManager()57cdf0e10cSrcweir LifeTimeManager::~LifeTimeManager()
58cdf0e10cSrcweir {
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
impl_isDisposed(bool bAssert)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
impl_canStartApiCall()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
impl_registerApiCall(sal_Bool bLongLastingCall)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
impl_unregisterApiCall(sal_Bool bLongLastingCall)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
dispose()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 =
144cdf0e10cSrcweir 			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 
CloseableLifeTimeManager(::com::sun::star::util::XCloseable * pCloseable,::com::sun::star::lang::XComponent * pComponent,sal_Bool bLongLastingCallsCancelable)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 
~CloseableLifeTimeManager()183cdf0e10cSrcweir CloseableLifeTimeManager::~CloseableLifeTimeManager()
184cdf0e10cSrcweir {
185cdf0e10cSrcweir }
186cdf0e10cSrcweir 
impl_isDisposedOrClosed(bool bAssert)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
g_close_startTryClose(sal_Bool bDeliverOwnership)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 =
237cdf0e10cSrcweir 			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(
242cdf0e10cSrcweir 						::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
g_close_endTryClose(sal_Bool bDeliverOwnership,sal_Bool)268cdf0e10cSrcweir ::g_close_endTryClose(sal_Bool bDeliverOwnership, sal_Bool /* bMyVeto */ )
269cdf0e10cSrcweir {
270cdf0e10cSrcweir 	//this method is called, if the try to close was not successfull
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
g_close_isNeedToCancelLongLastingCalls(sal_Bool bDeliverOwnership,util::CloseVetoException & ex)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
g_close_endTryClose_doClose()312cdf0e10cSrcweir ::g_close_endTryClose_doClose()
313cdf0e10cSrcweir {
314cdf0e10cSrcweir 	//this method is called, if the try to close was successfull
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
impl_setOwnership(sal_Bool bDeliverOwnership,sal_Bool bMyVeto)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
impl_shouldCloseAtNextChance()333cdf0e10cSrcweir ::impl_shouldCloseAtNextChance()
334cdf0e10cSrcweir {
335cdf0e10cSrcweir 	return m_bOwnership;
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 	void CloseableLifeTimeManager
impl_apiCallCountReachedNull()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
impl_doClose()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 	{
366cdf0e10cSrcweir 		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(
371cdf0e10cSrcweir 						::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
g_addCloseListener(const uno::Reference<util::XCloseListener> & xListener)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
impl_canStartApiCall()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
startApiCall(sal_Bool bLongLastingCall)450cdf0e10cSrcweir ::startApiCall(sal_Bool bLongLastingCall)
451cdf0e10cSrcweir {
452cdf0e10cSrcweir 	//Mutex needs to be acquired exactly ones; will be released inbetween
453cdf0e10cSrcweir 	//mutex is requiered 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 
~LifeTimeGuard()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
506cdf0e10cSrcweir 	//check wether 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