xref: /trunk/main/chart2/source/tools/LifeTime.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1cde9e8dcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3cde9e8dcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4cde9e8dcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5cde9e8dcSAndrew Rist  * distributed with this work for additional information
6cde9e8dcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7cde9e8dcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8cde9e8dcSAndrew Rist  * "License"); you may not use this file except in compliance
9cde9e8dcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11cde9e8dcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13cde9e8dcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14cde9e8dcSAndrew Rist  * software distributed under the License is distributed on an
15cde9e8dcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16cde9e8dcSAndrew Rist  * KIND, either express or implied.  See the License for the
17cde9e8dcSAndrew Rist  * specific language governing permissions and limitations
18cde9e8dcSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20cde9e8dcSAndrew Rist  *************************************************************/
21cde9e8dcSAndrew Rist 
22cde9e8dcSAndrew 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 =
144*be099857Smseidel             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 =
237*be099857Smseidel             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(
242*be099857Smseidel                         ::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 {
27007a3d7f1SPedro Giffuni     //this method is called, if the try to close was not successful
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 {
31407a3d7f1SPedro Giffuni     //this method is called, if the try to close was successful
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     {
366*be099857Smseidel         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(
371*be099857Smseidel                         ::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
453de337080SJohn Bampton     //mutex is required 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
50674cbd1f1SMatthias Seidel     //check whether 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