1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <osl/mutex.hxx>
30 #include <cppuhelper/weakagg.hxx>
31 #include <cppuhelper/interfacecontainer.hxx>
32 #include "cppuhelper/exc_hlp.hxx"
35 using namespace com::sun::star::uno
;
41 // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#)
42 inline static Mutex
& getWeakMutex() SAL_THROW(())
44 static Mutex
* s_pMutex
= 0;
46 s_pMutex
= new Mutex();
50 //------------------------------------------------------------------------
51 //-- OWeakConnectionPoint ----------------------------------------------------
52 //------------------------------------------------------------------------
53 class OWeakConnectionPoint
: public XAdapter
57 Hold the weak object without an acquire (only the pointer).
59 OWeakConnectionPoint( OWeakObject
* pObj
) SAL_THROW(())
62 , m_aReferences( getWeakMutex() )
66 Any SAL_CALL
queryInterface( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
);
67 void SAL_CALL
acquire() throw();
68 void SAL_CALL
release() throw();
71 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> SAL_CALL
queryAdapted() throw(::com::sun::star::uno::RuntimeException
);
72 void SAL_CALL
addReference( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XReference
>& xRef
) throw(::com::sun::star::uno::RuntimeException
);
73 void SAL_CALL
removeReference( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XReference
>& xRef
) throw(::com::sun::star::uno::RuntimeException
);
75 /// Called from the weak object if the reference count goes to zero.
76 void SAL_CALL
dispose() throw(::com::sun::star::uno::RuntimeException
);
79 OWeakConnectionPoint(OWeakConnectionPoint
&); // not defined
80 void operator =(OWeakConnectionPoint
&); // not defined
82 virtual ~OWeakConnectionPoint() {}
84 /// The reference counter.
85 oslInterlockedCount m_aRefCount
;
87 OWeakObject
* m_pObject
;
88 /// The container to hold the weak references
89 OInterfaceContainerHelper m_aReferences
;
93 Any SAL_CALL
OWeakConnectionPoint::queryInterface( const Type
& rType
)
94 throw(com::sun::star::uno::RuntimeException
)
96 return ::cppu::queryInterface(
97 rType
, static_cast< XAdapter
* >( this ), static_cast< XInterface
* >( this ) );
101 void SAL_CALL
OWeakConnectionPoint::acquire() throw()
103 osl_atomic_increment( &m_aRefCount
);
107 void SAL_CALL
OWeakConnectionPoint::release() throw()
109 if (! osl_atomic_decrement( &m_aRefCount
))
113 void SAL_CALL
OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException
)
116 OInterfaceIteratorHelper
aIt( m_aReferences
);
117 while( aIt
.hasMoreElements() )
121 ((XReference
*)aIt
.next())->dispose();
123 catch (com::sun::star::lang::DisposedException
&) {}
124 catch (RuntimeException
&)
126 ex
= cppu::getCaughtException();
131 cppu::throwException(ex
);
136 Reference
< XInterface
> SAL_CALL
OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException
)
138 Reference
< XInterface
> ret
;
140 ClearableMutexGuard
guard(getWeakMutex());
144 oslInterlockedCount n
= osl_atomic_increment( &m_pObject
->m_refCount
);
148 // The refence is incremented. The object cannot be destroyed.
149 // Release the guard at the earliest point.
151 // WeakObject has a (XInterface *) cast operator
153 n
= osl_atomic_decrement( &m_pObject
->m_refCount
);
156 // Another thread wait in the dispose method at the guard
157 n
= osl_atomic_decrement( &m_pObject
->m_refCount
);
164 void SAL_CALL
OWeakConnectionPoint::addReference(const Reference
< XReference
>& rRef
)
165 throw(::com::sun::star::uno::RuntimeException
)
167 m_aReferences
.addInterface( (const Reference
< XInterface
> &)rRef
);
171 void SAL_CALL
OWeakConnectionPoint::removeReference(const Reference
< XReference
>& rRef
)
172 throw(::com::sun::star::uno::RuntimeException
)
174 m_aReferences
.removeInterface( (const Reference
< XInterface
> &)rRef
);
178 //------------------------------------------------------------------------
179 //-- OWeakObject -------------------------------------------------------
180 //------------------------------------------------------------------------
183 // Accidentally occurs in msvc mapfile = > had to be outlined.
184 OWeakObject::OWeakObject() SAL_THROW(())
186 m_pWeakConnectionPoint( 0 )
192 Any SAL_CALL
OWeakObject::queryInterface( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
)
194 return ::cppu::queryInterface(
196 static_cast< XWeak
* >( this ), static_cast< XInterface
* >( this ) );
200 void SAL_CALL
OWeakObject::acquire() throw()
202 osl_atomic_increment( &m_refCount
);
206 void SAL_CALL
OWeakObject::release() throw()
208 if (osl_atomic_decrement( &m_refCount
) == 0) {
209 // notify/clear all weak-refs before object's dtor is executed
210 // (which may check weak-refs to this object):
211 disposeWeakConnectionPoint();
217 void OWeakObject::disposeWeakConnectionPoint()
219 OSL_PRECOND( m_refCount
== 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
220 if (m_pWeakConnectionPoint
!= 0) {
221 OWeakConnectionPoint
* const p
= m_pWeakConnectionPoint
;
222 m_pWeakConnectionPoint
= 0;
226 catch (RuntimeException
const& exc
) {
229 exc
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr() );
230 static_cast<void>(exc
);
236 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException
) )
241 Reference
< XAdapter
> SAL_CALL
OWeakObject::queryAdapter()
242 throw (::com::sun::star::uno::RuntimeException
)
244 if (!m_pWeakConnectionPoint
)
246 // only acquire mutex if member is not created
247 MutexGuard
aGuard( getWeakMutex() );
248 if( !m_pWeakConnectionPoint
)
250 OWeakConnectionPoint
* p
= new OWeakConnectionPoint(this);
252 m_pWeakConnectionPoint
= p
;
256 return m_pWeakConnectionPoint
;
259 //------------------------------------------------------------------------
260 //-- OWeakAggObject ----------------------------------------------------
261 //------------------------------------------------------------------------
262 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException
) )
267 void OWeakAggObject::acquire() throw()
269 Reference
<XInterface
> x( xDelegator
);
273 OWeakObject::acquire();
277 void OWeakAggObject::release() throw()
279 Reference
<XInterface
> x( xDelegator
);
283 OWeakObject::release();
287 Any
OWeakAggObject::queryInterface( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
)
289 Reference
< XInterface
> x( xDelegator
); // harden ref
290 return (x
.is() ? x
->queryInterface( rType
) : queryAggregation( rType
));
294 Any
OWeakAggObject::queryAggregation( const Type
& rType
) throw(::com::sun::star::uno::RuntimeException
)
296 return ::cppu::queryInterface(
298 static_cast< XInterface
* >( static_cast< OWeakObject
* >( this ) ),
299 static_cast< XAggregation
* >( this ),
300 static_cast< XWeak
* >( this ) );
304 void OWeakAggObject::setDelegator( const Reference
<XInterface
> & rDelegator
) throw(::com::sun::star::uno::RuntimeException
)
306 xDelegator
= rDelegator
;
325 //------------------------------------------------------------------------
326 //-- OWeakRefListener -----------------------------------------------------
327 //------------------------------------------------------------------------
328 class OWeakRefListener
: public XReference
331 OWeakRefListener(const OWeakRefListener
& rRef
) SAL_THROW(());
332 OWeakRefListener(const Reference
< XInterface
>& xInt
) SAL_THROW(());
333 virtual ~OWeakRefListener() SAL_THROW(());
336 Any SAL_CALL
queryInterface( const Type
& rType
) throw(RuntimeException
);
337 void SAL_CALL
acquire() throw();
338 void SAL_CALL
release() throw();
341 void SAL_CALL
dispose() throw(::com::sun::star::uno::RuntimeException
);
343 /// The reference counter.
344 oslInterlockedCount m_aRefCount
;
345 /// The connection point of the weak object
346 Reference
< XAdapter
> m_XWeakConnectionPoint
;
349 OWeakRefListener
& SAL_CALL
operator=(const OWeakRefListener
& rRef
) SAL_THROW(());
352 OWeakRefListener::OWeakRefListener(const OWeakRefListener
& rRef
) SAL_THROW(())
353 : com::sun::star::uno::XReference()
358 m_XWeakConnectionPoint
= rRef
.m_XWeakConnectionPoint
;
360 if (m_XWeakConnectionPoint
.is())
362 m_XWeakConnectionPoint
->addReference((XReference
*)this);
365 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
366 osl_atomic_decrement( &m_aRefCount
);
369 OWeakRefListener::OWeakRefListener(const Reference
< XInterface
>& xInt
) SAL_THROW(())
374 Reference
< XWeak
> xWeak( Reference
< XWeak
>::query( xInt
) );
378 m_XWeakConnectionPoint
= xWeak
->queryAdapter();
380 if (m_XWeakConnectionPoint
.is())
382 m_XWeakConnectionPoint
->addReference((XReference
*)this);
386 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
387 osl_atomic_decrement( &m_aRefCount
);
390 OWeakRefListener::~OWeakRefListener() SAL_THROW(())
394 if (m_XWeakConnectionPoint
.is())
396 acquire(); // dont die again
397 m_XWeakConnectionPoint
->removeReference((XReference
*)this);
400 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
404 Any SAL_CALL
OWeakRefListener::queryInterface( const Type
& rType
) throw(RuntimeException
)
406 return ::cppu::queryInterface(
407 rType
, static_cast< XReference
* >( this ), static_cast< XInterface
* >( this ) );
411 void SAL_CALL
OWeakRefListener::acquire() throw()
413 osl_atomic_increment( &m_aRefCount
);
417 void SAL_CALL
OWeakRefListener::release() throw()
419 if( ! osl_atomic_decrement( &m_aRefCount
) )
423 void SAL_CALL
OWeakRefListener::dispose()
424 throw(::com::sun::star::uno::RuntimeException
)
426 Reference
< XAdapter
> xAdp
;
428 MutexGuard
guard(cppu::getWeakMutex());
429 if( m_XWeakConnectionPoint
.is() )
431 xAdp
= m_XWeakConnectionPoint
;
432 m_XWeakConnectionPoint
.clear();
437 xAdp
->removeReference((XReference
*)this);
440 //------------------------------------------------------------------------
441 //-- WeakReferenceHelper ----------------------------------------------------------
442 //------------------------------------------------------------------------
443 WeakReferenceHelper::WeakReferenceHelper(const Reference
< XInterface
>& xInt
) SAL_THROW(())
448 m_pImpl
= new OWeakRefListener(xInt
);
453 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper
& rWeakRef
) SAL_THROW(())
456 Reference
< XInterface
> xInt( rWeakRef
.get() );
459 m_pImpl
= new OWeakRefListener(xInt
);
464 void WeakReferenceHelper::clear() SAL_THROW(())
470 if (m_pImpl
->m_XWeakConnectionPoint
.is())
472 m_pImpl
->m_XWeakConnectionPoint
->removeReference(
473 (XReference
*)m_pImpl
);
474 m_pImpl
->m_XWeakConnectionPoint
.clear();
480 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
483 WeakReferenceHelper
& WeakReferenceHelper::operator=(const WeakReferenceHelper
& rWeakRef
) SAL_THROW(())
485 if (this == &rWeakRef
)
489 Reference
< XInterface
> xInt( rWeakRef
.get() );
490 return operator = ( xInt
);
493 WeakReferenceHelper
& SAL_CALL
494 WeakReferenceHelper::operator= (const Reference
< XInterface
> & xInt
)
502 m_pImpl
= new OWeakRefListener(xInt
);
506 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
510 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW(())
515 Reference
< XInterface
> WeakReferenceHelper::get() const SAL_THROW(())
519 Reference
< XAdapter
> xAdp
;
521 MutexGuard
guard(cppu::getWeakMutex());
522 if( m_pImpl
&& m_pImpl
->m_XWeakConnectionPoint
.is() )
523 xAdp
= m_pImpl
->m_XWeakConnectionPoint
;
527 return xAdp
->queryAdapted();
529 catch (RuntimeException
&) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
531 return Reference
< XInterface
>();
539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */