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