bump product version to 4.1.6.2
[LibreOffice.git] / cppuhelper / source / weak.cxx
blob8bba4da4101b6be771c10f1b094cb15981c5a52f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/mutex.hxx>
21 #include <cppuhelper/weakagg.hxx>
22 #include <cppuhelper/interfacecontainer.hxx>
23 #include "cppuhelper/exc_hlp.hxx"
25 using namespace osl;
26 using namespace com::sun::star::uno;
28 /** */ //for docpp
29 namespace cppu
32 // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#)
33 inline static Mutex & getWeakMutex() SAL_THROW(())
35 static Mutex * s_pMutex = 0;
36 if (! s_pMutex)
37 s_pMutex = new Mutex();
38 return *s_pMutex;
41 //------------------------------------------------------------------------
42 //-- OWeakConnectionPoint ----------------------------------------------------
43 //------------------------------------------------------------------------
44 class OWeakConnectionPoint : public XAdapter
46 public:
47 /**
48 Hold the weak object without an acquire (only the pointer).
50 OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW(())
51 : m_aRefCount( 0 )
52 , m_pObject(pObj)
53 , m_aReferences( getWeakMutex() )
56 // XInterface
57 Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
58 void SAL_CALL acquire() throw();
59 void SAL_CALL release() throw();
61 // XAdapter
62 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException);
63 void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
64 void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
66 /// Called from the weak object if the reference count goes to zero.
67 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
69 private:
70 OWeakConnectionPoint(OWeakConnectionPoint &); // not defined
71 void operator =(OWeakConnectionPoint &); // not defined
73 virtual ~OWeakConnectionPoint() {}
75 /// The reference counter.
76 oslInterlockedCount m_aRefCount;
77 /// The weak object
78 OWeakObject* m_pObject;
79 /// The container to hold the weak references
80 OInterfaceContainerHelper m_aReferences;
83 // XInterface
84 Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
85 throw(com::sun::star::uno::RuntimeException)
87 return ::cppu::queryInterface(
88 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
91 // XInterface
92 void SAL_CALL OWeakConnectionPoint::acquire() throw()
94 osl_atomic_increment( &m_aRefCount );
97 // XInterface
98 void SAL_CALL OWeakConnectionPoint::release() throw()
100 if (! osl_atomic_decrement( &m_aRefCount ))
101 delete this;
104 void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
106 Any ex;
107 OInterfaceIteratorHelper aIt( m_aReferences );
108 while( aIt.hasMoreElements() )
112 ((XReference *)aIt.next())->dispose();
114 catch (com::sun::star::lang::DisposedException &) {}
115 catch (RuntimeException &)
117 ex = cppu::getCaughtException();
120 if (ex.hasValue())
122 cppu::throwException(ex);
126 // XInterface
127 Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException)
129 Reference< XInterface > ret;
131 ClearableMutexGuard guard(getWeakMutex());
133 if (m_pObject)
135 oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
137 if (n > 1)
139 // The refence is incremented. The object cannot be destroyed.
140 // Release the guard at the earliest point.
141 guard.clear();
142 // WeakObject has a (XInterface *) cast operator
143 ret = *m_pObject;
144 n = osl_atomic_decrement( &m_pObject->m_refCount );
146 else
147 // Another thread wait in the dispose method at the guard
148 n = osl_atomic_decrement( &m_pObject->m_refCount );
151 return ret;
154 // XInterface
155 void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
156 throw(::com::sun::star::uno::RuntimeException)
158 m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
161 // XInterface
162 void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
163 throw(::com::sun::star::uno::RuntimeException)
165 m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
169 //------------------------------------------------------------------------
170 //-- OWeakObject -------------------------------------------------------
171 //------------------------------------------------------------------------
173 #ifdef _MSC_VER
174 // Accidentally occurs in msvc mapfile = > had to be outlined.
175 OWeakObject::OWeakObject() SAL_THROW(())
176 : m_refCount( 0 ),
177 m_pWeakConnectionPoint( 0 )
180 #endif
182 // XInterface
183 Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
185 return ::cppu::queryInterface(
186 rType,
187 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
190 // XInterface
191 void SAL_CALL OWeakObject::acquire() throw()
193 osl_atomic_increment( &m_refCount );
196 // XInterface
197 void SAL_CALL OWeakObject::release() throw()
199 if (osl_atomic_decrement( &m_refCount ) == 0) {
200 // notify/clear all weak-refs before object's dtor is executed
201 // (which may check weak-refs to this object):
202 disposeWeakConnectionPoint();
203 // destroy object:
204 delete this;
208 void OWeakObject::disposeWeakConnectionPoint()
210 OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
211 if (m_pWeakConnectionPoint != 0) {
212 OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
213 m_pWeakConnectionPoint = 0;
214 try {
215 p->dispose();
217 catch (RuntimeException const& exc) {
218 OSL_FAIL(
219 OUStringToOString(
220 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
221 static_cast<void>(exc);
223 p->release();
227 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) )
231 // XWeak
232 Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
233 throw (::com::sun::star::uno::RuntimeException)
235 if (!m_pWeakConnectionPoint)
237 // only acquire mutex if member is not created
238 MutexGuard aGuard( getWeakMutex() );
239 if( !m_pWeakConnectionPoint )
241 OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
242 p->acquire();
243 m_pWeakConnectionPoint = p;
247 return m_pWeakConnectionPoint;
250 //------------------------------------------------------------------------
251 //-- OWeakAggObject ----------------------------------------------------
252 //------------------------------------------------------------------------
253 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) )
257 // XInterface
258 void OWeakAggObject::acquire() throw()
260 Reference<XInterface > x( xDelegator );
261 if (x.is())
262 x->acquire();
263 else
264 OWeakObject::acquire();
267 // XInterface
268 void OWeakAggObject::release() throw()
270 Reference<XInterface > x( xDelegator );
271 if (x.is())
272 x->release();
273 else
274 OWeakObject::release();
277 // XInterface
278 Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
280 Reference< XInterface > x( xDelegator ); // harden ref
281 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
284 // XAggregation
285 Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
287 return ::cppu::queryInterface(
288 rType,
289 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
290 static_cast< XAggregation * >( this ),
291 static_cast< XWeak * >( this ) );
294 // XAggregation
295 void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException)
297 xDelegator = rDelegator;
302 /** */ //for docpp
303 namespace com
305 /** */ //for docpp
306 namespace sun
308 /** */ //for docpp
309 namespace star
311 /** */ //for docpp
312 namespace uno
316 //------------------------------------------------------------------------
317 //-- OWeakRefListener -----------------------------------------------------
318 //------------------------------------------------------------------------
319 class OWeakRefListener : public XReference
321 public:
322 OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(());
323 OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(());
324 virtual ~OWeakRefListener() SAL_THROW(());
326 // XInterface
327 Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException);
328 void SAL_CALL acquire() throw();
329 void SAL_CALL release() throw();
331 // XReference
332 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
334 /// The reference counter.
335 oslInterlockedCount m_aRefCount;
336 /// The connection point of the weak object
337 Reference< XAdapter > m_XWeakConnectionPoint;
339 private:
340 OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW(());
343 OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(())
344 : com::sun::star::uno::XReference()
345 , m_aRefCount( 1 )
349 m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint;
351 if (m_XWeakConnectionPoint.is())
353 m_XWeakConnectionPoint->addReference((XReference*)this);
356 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
357 osl_atomic_decrement( &m_aRefCount );
360 OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(())
361 : m_aRefCount( 1 )
365 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
367 if (xWeak.is())
369 m_XWeakConnectionPoint = xWeak->queryAdapter();
371 if (m_XWeakConnectionPoint.is())
373 m_XWeakConnectionPoint->addReference((XReference*)this);
377 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
378 osl_atomic_decrement( &m_aRefCount );
381 OWeakRefListener::~OWeakRefListener() SAL_THROW(())
385 if (m_XWeakConnectionPoint.is())
387 acquire(); // dont die again
388 m_XWeakConnectionPoint->removeReference((XReference*)this);
391 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
394 // XInterface
395 Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException)
397 return ::cppu::queryInterface(
398 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
401 // XInterface
402 void SAL_CALL OWeakRefListener::acquire() throw()
404 osl_atomic_increment( &m_aRefCount );
407 // XInterface
408 void SAL_CALL OWeakRefListener::release() throw()
410 if( ! osl_atomic_decrement( &m_aRefCount ) )
411 delete this;
414 void SAL_CALL OWeakRefListener::dispose()
415 throw(::com::sun::star::uno::RuntimeException)
417 Reference< XAdapter > xAdp;
419 MutexGuard guard(cppu::getWeakMutex());
420 if( m_XWeakConnectionPoint.is() )
422 xAdp = m_XWeakConnectionPoint;
423 m_XWeakConnectionPoint.clear();
427 if( xAdp.is() )
428 xAdp->removeReference((XReference*)this);
431 //------------------------------------------------------------------------
432 //-- WeakReferenceHelper ----------------------------------------------------------
433 //------------------------------------------------------------------------
434 WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW(())
435 : m_pImpl( 0 )
437 if (xInt.is())
439 m_pImpl = new OWeakRefListener(xInt);
440 m_pImpl->acquire();
444 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
445 : m_pImpl( 0 )
447 Reference< XInterface > xInt( rWeakRef.get() );
448 if (xInt.is())
450 m_pImpl = new OWeakRefListener(xInt);
451 m_pImpl->acquire();
455 void WeakReferenceHelper::clear() SAL_THROW(())
459 if (m_pImpl)
461 if (m_pImpl->m_XWeakConnectionPoint.is())
463 m_pImpl->m_XWeakConnectionPoint->removeReference(
464 (XReference*)m_pImpl);
465 m_pImpl->m_XWeakConnectionPoint.clear();
467 m_pImpl->release();
468 m_pImpl = 0;
471 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
474 WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
476 if (this == &rWeakRef)
478 return *this;
480 Reference< XInterface > xInt( rWeakRef.get() );
481 return operator = ( xInt );
484 WeakReferenceHelper & SAL_CALL
485 WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
486 SAL_THROW(())
490 clear();
491 if (xInt.is())
493 m_pImpl = new OWeakRefListener(xInt);
494 m_pImpl->acquire();
497 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
498 return *this;
501 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW(())
503 clear();
506 Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW(())
510 Reference< XAdapter > xAdp;
512 MutexGuard guard(cppu::getWeakMutex());
513 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
514 xAdp = m_pImpl->m_XWeakConnectionPoint;
517 if (xAdp.is())
518 return xAdp->queryAdapted();
520 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
522 return Reference< XInterface >();
530 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */