update dev300-m58
[ooovba.git] / cppuhelper / source / weak.cxx
blobaed67e4aadce61ff51cc9e86d92902a446c2b01a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: weak.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppuhelper.hxx"
33 #include <osl/mutex.hxx>
34 #ifndef _CPPU_WEAKAGG_HXX_
35 #include <cppuhelper/weakagg.hxx>
36 #endif
37 #ifndef _CPPU_HELPER_INTERFACECONTAINER_HXX_
38 #include <cppuhelper/interfacecontainer.hxx>
39 #endif
40 #include "cppuhelper/exc_hlp.hxx"
42 using namespace osl;
43 using namespace com::sun::star::uno;
45 /** */ //for docpp
46 namespace cppu
49 // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#)
50 inline static Mutex & getWeakMutex() SAL_THROW( () )
52 static Mutex * s_pMutex = 0;
53 if (! s_pMutex)
54 s_pMutex = new Mutex();
55 return *s_pMutex;
58 //------------------------------------------------------------------------
59 //-- OWeakConnectionPoint ----------------------------------------------------
60 //------------------------------------------------------------------------
61 class OWeakConnectionPoint : public XAdapter
63 public:
64 /**
65 Hold the weak object without an acquire (only the pointer).
67 OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW( () )
68 : m_aRefCount( 0 )
69 , m_pObject(pObj)
70 , m_aReferences( getWeakMutex() )
73 // XInterface
74 Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
75 void SAL_CALL acquire() throw();
76 void SAL_CALL release() throw();
78 // XAdapter
79 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException);
80 void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
81 void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
83 /// Called from the weak object if the reference count goes to zero.
84 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
86 private:
87 OWeakConnectionPoint(OWeakConnectionPoint &); // not defined
88 void operator =(OWeakConnectionPoint &); // not defined
90 virtual ~OWeakConnectionPoint() {}
92 /// The reference counter.
93 oslInterlockedCount m_aRefCount;
94 /// The weak object
95 OWeakObject* m_pObject;
96 /// The container to hold the weak references
97 OInterfaceContainerHelper m_aReferences;
100 // XInterface
101 Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
102 throw(com::sun::star::uno::RuntimeException)
104 return ::cppu::queryInterface(
105 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
108 // XInterface
109 void SAL_CALL OWeakConnectionPoint::acquire() throw()
111 osl_incrementInterlockedCount( &m_aRefCount );
114 // XInterface
115 void SAL_CALL OWeakConnectionPoint::release() throw()
117 if (! osl_decrementInterlockedCount( &m_aRefCount ))
118 delete this;
121 void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
123 Any ex;
124 OInterfaceIteratorHelper aIt( m_aReferences );
125 while( aIt.hasMoreElements() )
129 ((XReference *)aIt.next())->dispose();
131 catch (com::sun::star::lang::DisposedException &) {}
132 catch (RuntimeException &)
134 ex = cppu::getCaughtException();
137 if (ex.hasValue())
139 cppu::throwException(ex);
143 // XInterface
144 Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException)
146 Reference< XInterface > ret;
148 ClearableMutexGuard guard(getWeakMutex());
150 if (m_pObject)
152 oslInterlockedCount n = osl_incrementInterlockedCount( &m_pObject->m_refCount );
154 if (n > 1)
156 // The refence is incremented. The object cannot be destroyed.
157 // Release the guard at the earliest point.
158 guard.clear();
159 // WeakObject has a (XInterface *) cast operator
160 ret = *m_pObject;
161 n = osl_decrementInterlockedCount( &m_pObject->m_refCount );
163 else
164 // Another thread wait in the dispose method at the guard
165 n = osl_decrementInterlockedCount( &m_pObject->m_refCount );
168 return ret;
171 // XInterface
172 void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
173 throw(::com::sun::star::uno::RuntimeException)
175 m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
178 // XInterface
179 void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
180 throw(::com::sun::star::uno::RuntimeException)
182 m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
186 //------------------------------------------------------------------------
187 //-- OWeakObject -------------------------------------------------------
188 //------------------------------------------------------------------------
190 #ifdef _MSC_VER
191 // Accidentally occurs in msvc mapfile = > had to be outlined.
192 OWeakObject::OWeakObject() SAL_THROW( () )
193 : m_refCount( 0 ),
194 m_pWeakConnectionPoint( 0 )
197 #endif
199 // XInterface
200 Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
202 return ::cppu::queryInterface(
203 rType,
204 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
207 // XInterface
208 void SAL_CALL OWeakObject::acquire() throw()
210 osl_incrementInterlockedCount( &m_refCount );
213 // XInterface
214 void SAL_CALL OWeakObject::release() throw()
216 if (osl_decrementInterlockedCount( &m_refCount ) == 0) {
217 // notify/clear all weak-refs before object's dtor is executed
218 // (which may check weak-refs to this object):
219 if (m_pWeakConnectionPoint != 0) {
220 OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
221 m_pWeakConnectionPoint = 0;
222 try {
223 p->dispose();
225 catch (RuntimeException const& exc) {
226 OSL_ENSURE(
227 false, OUStringToOString(
228 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
229 static_cast<void>(exc);
231 p->release();
233 // destroy object:
234 delete this;
238 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) )
242 // XWeak
243 Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
244 throw (::com::sun::star::uno::RuntimeException)
246 if (!m_pWeakConnectionPoint)
248 // only acquire mutex if member is not created
249 MutexGuard aGuard( getWeakMutex() );
250 if( !m_pWeakConnectionPoint )
252 OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
253 p->acquire();
254 m_pWeakConnectionPoint = p;
258 return m_pWeakConnectionPoint;
261 //------------------------------------------------------------------------
262 //-- OWeakAggObject ----------------------------------------------------
263 //------------------------------------------------------------------------
264 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) )
268 // XInterface
269 void OWeakAggObject::acquire() throw()
271 Reference<XInterface > x( xDelegator );
272 if (x.is())
273 x->acquire();
274 else
275 OWeakObject::acquire();
278 // XInterface
279 void OWeakAggObject::release() throw()
281 Reference<XInterface > x( xDelegator );
282 if (x.is())
283 x->release();
284 else
285 OWeakObject::release();
288 // XInterface
289 Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
291 Reference< XInterface > x( xDelegator ); // harden ref
292 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
294 // // set rOut to zero, if failed
295 // if( !xDelegator.queryHardRef( aUik, rOut ) )
296 // {
297 // XInterfaceRef x;
298 // if( !xDelegator.queryHardRef( ((XInterface*)0)->getSmartUik(), x ) )
299 // // reference is not valid
300 // queryAggregation( aUik, rOut );
301 // }
302 // return rOut.is();
305 // XAggregation
306 Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
308 return ::cppu::queryInterface(
309 rType,
310 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
311 static_cast< XAggregation * >( this ),
312 static_cast< XWeak * >( this ) );
315 // XAggregation
316 void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException)
318 xDelegator = rDelegator;
323 /** */ //for docpp
324 namespace com
326 /** */ //for docpp
327 namespace sun
329 /** */ //for docpp
330 namespace star
332 /** */ //for docpp
333 namespace uno
337 //------------------------------------------------------------------------
338 //-- OWeakRefListener -----------------------------------------------------
339 //------------------------------------------------------------------------
340 class OWeakRefListener : public XReference
342 public:
343 OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () );
344 OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () );
345 virtual ~OWeakRefListener() SAL_THROW( () );
347 // XInterface
348 Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException);
349 void SAL_CALL acquire() throw();
350 void SAL_CALL release() throw();
352 // XReference
353 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
355 /// The reference counter.
356 oslInterlockedCount m_aRefCount;
357 /// The connection point of the weak object
358 Reference< XAdapter > m_XWeakConnectionPoint;
360 private:
361 OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW( () );
364 OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () )
365 : com::sun::star::uno::XReference()
366 , m_aRefCount( 1 )
370 m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint;
372 if (m_XWeakConnectionPoint.is())
374 m_XWeakConnectionPoint->addReference((XReference*)this);
377 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
378 osl_decrementInterlockedCount( &m_aRefCount );
381 OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () )
382 : m_aRefCount( 1 )
386 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
388 if (xWeak.is())
390 m_XWeakConnectionPoint = xWeak->queryAdapter();
392 if (m_XWeakConnectionPoint.is())
394 m_XWeakConnectionPoint->addReference((XReference*)this);
398 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
399 osl_decrementInterlockedCount( &m_aRefCount );
402 OWeakRefListener::~OWeakRefListener() SAL_THROW( () )
406 if (m_XWeakConnectionPoint.is())
408 acquire(); // dont die again
409 m_XWeakConnectionPoint->removeReference((XReference*)this);
412 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
415 // XInterface
416 Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException)
418 return ::cppu::queryInterface(
419 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
422 // XInterface
423 void SAL_CALL OWeakRefListener::acquire() throw()
425 osl_incrementInterlockedCount( &m_aRefCount );
428 // XInterface
429 void SAL_CALL OWeakRefListener::release() throw()
431 if( ! osl_decrementInterlockedCount( &m_aRefCount ) )
432 delete this;
435 void SAL_CALL OWeakRefListener::dispose()
436 throw(::com::sun::star::uno::RuntimeException)
438 Reference< XAdapter > xAdp;
440 MutexGuard guard(cppu::getWeakMutex());
441 if( m_XWeakConnectionPoint.is() )
443 xAdp = m_XWeakConnectionPoint;
444 m_XWeakConnectionPoint.clear();
448 if( xAdp.is() )
449 xAdp->removeReference((XReference*)this);
452 //------------------------------------------------------------------------
453 //-- WeakReferenceHelper ----------------------------------------------------------
454 //------------------------------------------------------------------------
455 WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW( () )
456 : m_pImpl( 0 )
458 if (xInt.is())
460 m_pImpl = new OWeakRefListener(xInt);
461 m_pImpl->acquire();
465 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW( () )
466 : m_pImpl( 0 )
468 Reference< XInterface > xInt( rWeakRef.get() );
469 if (xInt.is())
471 m_pImpl = new OWeakRefListener(xInt);
472 m_pImpl->acquire();
476 WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW( () )
480 if (this != &rWeakRef)
482 Reference< XInterface > xInt( rWeakRef.get() );
483 if (m_pImpl)
485 if (m_pImpl->m_XWeakConnectionPoint.is())
487 m_pImpl->m_XWeakConnectionPoint->removeReference((XReference*)m_pImpl);
488 m_pImpl->m_XWeakConnectionPoint.clear();
490 m_pImpl->release();
491 m_pImpl = 0;
493 if (xInt.is())
495 m_pImpl = new OWeakRefListener(xInt);
496 m_pImpl->acquire();
500 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
501 return *this;
504 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW( () )
508 if (m_pImpl)
510 if (m_pImpl->m_XWeakConnectionPoint.is())
512 m_pImpl->m_XWeakConnectionPoint->removeReference((XReference*)m_pImpl);
513 m_pImpl->m_XWeakConnectionPoint.clear();
515 m_pImpl->release();
516 m_pImpl = 0; // for safety
519 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
522 Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW( () )
526 Reference< XAdapter > xAdp;
528 MutexGuard guard(cppu::getWeakMutex());
529 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
530 xAdp = m_pImpl->m_XWeakConnectionPoint;
533 if (xAdp.is())
534 return xAdp->queryAdapted();
536 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
538 return Reference< XInterface >();