1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: weak.cxx,v $
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>
37 #ifndef _CPPU_HELPER_INTERFACECONTAINER_HXX_
38 #include <cppuhelper/interfacecontainer.hxx>
40 #include "cppuhelper/exc_hlp.hxx"
43 using namespace com::sun::star::uno
;
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;
54 s_pMutex
= new Mutex();
58 //------------------------------------------------------------------------
59 //-- OWeakConnectionPoint ----------------------------------------------------
60 //------------------------------------------------------------------------
61 class OWeakConnectionPoint
: public XAdapter
65 Hold the weak object without an acquire (only the pointer).
67 OWeakConnectionPoint( OWeakObject
* pObj
) SAL_THROW( () )
70 , m_aReferences( getWeakMutex() )
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();
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
);
87 OWeakConnectionPoint(OWeakConnectionPoint
&); // not defined
88 void operator =(OWeakConnectionPoint
&); // not defined
90 virtual ~OWeakConnectionPoint() {}
92 /// The reference counter.
93 oslInterlockedCount m_aRefCount
;
95 OWeakObject
* m_pObject
;
96 /// The container to hold the weak references
97 OInterfaceContainerHelper m_aReferences
;
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 ) );
109 void SAL_CALL
OWeakConnectionPoint::acquire() throw()
111 osl_incrementInterlockedCount( &m_aRefCount
);
115 void SAL_CALL
OWeakConnectionPoint::release() throw()
117 if (! osl_decrementInterlockedCount( &m_aRefCount
))
121 void SAL_CALL
OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException
)
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();
139 cppu::throwException(ex
);
144 Reference
< XInterface
> SAL_CALL
OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException
)
146 Reference
< XInterface
> ret
;
148 ClearableMutexGuard
guard(getWeakMutex());
152 oslInterlockedCount n
= osl_incrementInterlockedCount( &m_pObject
->m_refCount
);
156 // The refence is incremented. The object cannot be destroyed.
157 // Release the guard at the earliest point.
159 // WeakObject has a (XInterface *) cast operator
161 n
= osl_decrementInterlockedCount( &m_pObject
->m_refCount
);
164 // Another thread wait in the dispose method at the guard
165 n
= osl_decrementInterlockedCount( &m_pObject
->m_refCount
);
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
);
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 //------------------------------------------------------------------------
191 // Accidentally occurs in msvc mapfile = > had to be outlined.
192 OWeakObject::OWeakObject() SAL_THROW( () )
194 m_pWeakConnectionPoint( 0 )
200 Any SAL_CALL
OWeakObject::queryInterface( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
)
202 return ::cppu::queryInterface(
204 static_cast< XWeak
* >( this ), static_cast< XInterface
* >( this ) );
208 void SAL_CALL
OWeakObject::acquire() throw()
210 osl_incrementInterlockedCount( &m_refCount
);
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;
225 catch (RuntimeException
const& exc
) {
227 false, OUStringToOString(
228 exc
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr() );
229 static_cast<void>(exc
);
238 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException
) )
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);
254 m_pWeakConnectionPoint
= p
;
258 return m_pWeakConnectionPoint
;
261 //------------------------------------------------------------------------
262 //-- OWeakAggObject ----------------------------------------------------
263 //------------------------------------------------------------------------
264 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException
) )
269 void OWeakAggObject::acquire() throw()
271 Reference
<XInterface
> x( xDelegator
);
275 OWeakObject::acquire();
279 void OWeakAggObject::release() throw()
281 Reference
<XInterface
> x( xDelegator
);
285 OWeakObject::release();
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 ) )
298 // if( !xDelegator.queryHardRef( ((XInterface*)0)->getSmartUik(), x ) )
299 // // reference is not valid
300 // queryAggregation( aUik, rOut );
306 Any
OWeakAggObject::queryAggregation( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
)
308 return ::cppu::queryInterface(
310 static_cast< XInterface
* >( static_cast< OWeakObject
* >( this ) ),
311 static_cast< XAggregation
* >( this ),
312 static_cast< XWeak
* >( this ) );
316 void OWeakAggObject::setDelegator( const Reference
<XInterface
> & rDelegator
) throw(::com::sun::star::uno::RuntimeException
)
318 xDelegator
= rDelegator
;
337 //------------------------------------------------------------------------
338 //-- OWeakRefListener -----------------------------------------------------
339 //------------------------------------------------------------------------
340 class OWeakRefListener
: public XReference
343 OWeakRefListener(const OWeakRefListener
& rRef
) SAL_THROW( () );
344 OWeakRefListener(const Reference
< XInterface
>& xInt
) SAL_THROW( () );
345 virtual ~OWeakRefListener() SAL_THROW( () );
348 Any SAL_CALL
queryInterface( const Type
& rType
) throw(RuntimeException
);
349 void SAL_CALL
acquire() throw();
350 void SAL_CALL
release() throw();
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
;
361 OWeakRefListener
& SAL_CALL
operator=(const OWeakRefListener
& rRef
) SAL_THROW( () );
364 OWeakRefListener::OWeakRefListener(const OWeakRefListener
& rRef
) SAL_THROW( () )
365 : com::sun::star::uno::XReference()
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( () )
386 Reference
< XWeak
> xWeak( Reference
< XWeak
>::query( xInt
) );
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()
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 ) );
423 void SAL_CALL
OWeakRefListener::acquire() throw()
425 osl_incrementInterlockedCount( &m_aRefCount
);
429 void SAL_CALL
OWeakRefListener::release() throw()
431 if( ! osl_decrementInterlockedCount( &m_aRefCount
) )
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();
449 xAdp
->removeReference((XReference
*)this);
452 //------------------------------------------------------------------------
453 //-- WeakReferenceHelper ----------------------------------------------------------
454 //------------------------------------------------------------------------
455 WeakReferenceHelper::WeakReferenceHelper(const Reference
< XInterface
>& xInt
) SAL_THROW( () )
460 m_pImpl
= new OWeakRefListener(xInt
);
465 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper
& rWeakRef
) SAL_THROW( () )
468 Reference
< XInterface
> xInt( rWeakRef
.get() );
471 m_pImpl
= new OWeakRefListener(xInt
);
476 WeakReferenceHelper
& WeakReferenceHelper::operator=(const WeakReferenceHelper
& rWeakRef
) SAL_THROW( () )
480 if (this != &rWeakRef
)
482 Reference
< XInterface
> xInt( rWeakRef
.get() );
485 if (m_pImpl
->m_XWeakConnectionPoint
.is())
487 m_pImpl
->m_XWeakConnectionPoint
->removeReference((XReference
*)m_pImpl
);
488 m_pImpl
->m_XWeakConnectionPoint
.clear();
495 m_pImpl
= new OWeakRefListener(xInt
);
500 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
504 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW( () )
510 if (m_pImpl
->m_XWeakConnectionPoint
.is())
512 m_pImpl
->m_XWeakConnectionPoint
->removeReference((XReference
*)m_pImpl
);
513 m_pImpl
->m_XWeakConnectionPoint
.clear();
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
;
534 return xAdp
->queryAdapted();
536 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
538 return Reference
< XInterface
>();