Revert "new change in helpcontent2"
[LibreOffice.git] / cppuhelper / source / weak.cxx
blob266811f365a5ee2cf41fc6d5b8cf204be212c29b
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"
34 using namespace osl;
35 using namespace com::sun::star::uno;
37 /** */ //for docpp
38 namespace cppu
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;
45 if (! s_pMutex)
46 s_pMutex = new Mutex();
47 return *s_pMutex;
50 //------------------------------------------------------------------------
51 //-- OWeakConnectionPoint ----------------------------------------------------
52 //------------------------------------------------------------------------
53 class OWeakConnectionPoint : public XAdapter
55 public:
56 /**
57 Hold the weak object without an acquire (only the pointer).
59 OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW(())
60 : m_aRefCount( 0 )
61 , m_pObject(pObj)
62 , m_aReferences( getWeakMutex() )
65 // XInterface
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();
70 // XAdapter
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);
78 private:
79 OWeakConnectionPoint(OWeakConnectionPoint &); // not defined
80 void operator =(OWeakConnectionPoint &); // not defined
82 virtual ~OWeakConnectionPoint() {}
84 /// The reference counter.
85 oslInterlockedCount m_aRefCount;
86 /// The weak object
87 OWeakObject* m_pObject;
88 /// The container to hold the weak references
89 OInterfaceContainerHelper m_aReferences;
92 // XInterface
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 ) );
100 // XInterface
101 void SAL_CALL OWeakConnectionPoint::acquire() throw()
103 osl_atomic_increment( &m_aRefCount );
106 // XInterface
107 void SAL_CALL OWeakConnectionPoint::release() throw()
109 if (! osl_atomic_decrement( &m_aRefCount ))
110 delete this;
113 void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
115 Any ex;
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();
129 if (ex.hasValue())
131 cppu::throwException(ex);
135 // XInterface
136 Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException)
138 Reference< XInterface > ret;
140 ClearableMutexGuard guard(getWeakMutex());
142 if (m_pObject)
144 oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
146 if (n > 1)
148 // The refence is incremented. The object cannot be destroyed.
149 // Release the guard at the earliest point.
150 guard.clear();
151 // WeakObject has a (XInterface *) cast operator
152 ret = *m_pObject;
153 n = osl_atomic_decrement( &m_pObject->m_refCount );
155 else
156 // Another thread wait in the dispose method at the guard
157 n = osl_atomic_decrement( &m_pObject->m_refCount );
160 return ret;
163 // XInterface
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 );
170 // XInterface
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 //------------------------------------------------------------------------
182 #ifdef _MSC_VER
183 // Accidentally occurs in msvc mapfile = > had to be outlined.
184 OWeakObject::OWeakObject() SAL_THROW(())
185 : m_refCount( 0 ),
186 m_pWeakConnectionPoint( 0 )
189 #endif
191 // XInterface
192 Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
194 return ::cppu::queryInterface(
195 rType,
196 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
199 // XInterface
200 void SAL_CALL OWeakObject::acquire() throw()
202 osl_atomic_increment( &m_refCount );
205 // XInterface
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();
212 // destroy object:
213 delete this;
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;
223 try {
224 p->dispose();
226 catch (RuntimeException const& exc) {
227 OSL_FAIL(
228 OUStringToOString(
229 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
230 static_cast<void>(exc);
232 p->release();
236 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) )
240 // XWeak
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);
251 p->acquire();
252 m_pWeakConnectionPoint = p;
256 return m_pWeakConnectionPoint;
259 //------------------------------------------------------------------------
260 //-- OWeakAggObject ----------------------------------------------------
261 //------------------------------------------------------------------------
262 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) )
266 // XInterface
267 void OWeakAggObject::acquire() throw()
269 Reference<XInterface > x( xDelegator );
270 if (x.is())
271 x->acquire();
272 else
273 OWeakObject::acquire();
276 // XInterface
277 void OWeakAggObject::release() throw()
279 Reference<XInterface > x( xDelegator );
280 if (x.is())
281 x->release();
282 else
283 OWeakObject::release();
286 // XInterface
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 ));
293 // XAggregation
294 Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
296 return ::cppu::queryInterface(
297 rType,
298 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
299 static_cast< XAggregation * >( this ),
300 static_cast< XWeak * >( this ) );
303 // XAggregation
304 void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException)
306 xDelegator = rDelegator;
311 /** */ //for docpp
312 namespace com
314 /** */ //for docpp
315 namespace sun
317 /** */ //for docpp
318 namespace star
320 /** */ //for docpp
321 namespace uno
325 //------------------------------------------------------------------------
326 //-- OWeakRefListener -----------------------------------------------------
327 //------------------------------------------------------------------------
328 class OWeakRefListener : public XReference
330 public:
331 OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(());
332 OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(());
333 virtual ~OWeakRefListener() SAL_THROW(());
335 // XInterface
336 Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException);
337 void SAL_CALL acquire() throw();
338 void SAL_CALL release() throw();
340 // XReference
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;
348 private:
349 OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW(());
352 OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(())
353 : com::sun::star::uno::XReference()
354 , m_aRefCount( 1 )
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(())
370 : m_aRefCount( 1 )
374 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
376 if (xWeak.is())
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()
403 // XInterface
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 ) );
410 // XInterface
411 void SAL_CALL OWeakRefListener::acquire() throw()
413 osl_atomic_increment( &m_aRefCount );
416 // XInterface
417 void SAL_CALL OWeakRefListener::release() throw()
419 if( ! osl_atomic_decrement( &m_aRefCount ) )
420 delete this;
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();
436 if( xAdp.is() )
437 xAdp->removeReference((XReference*)this);
440 //------------------------------------------------------------------------
441 //-- WeakReferenceHelper ----------------------------------------------------------
442 //------------------------------------------------------------------------
443 WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW(())
444 : m_pImpl( 0 )
446 if (xInt.is())
448 m_pImpl = new OWeakRefListener(xInt);
449 m_pImpl->acquire();
453 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
454 : m_pImpl( 0 )
456 Reference< XInterface > xInt( rWeakRef.get() );
457 if (xInt.is())
459 m_pImpl = new OWeakRefListener(xInt);
460 m_pImpl->acquire();
464 void WeakReferenceHelper::clear() SAL_THROW(())
468 if (m_pImpl)
470 if (m_pImpl->m_XWeakConnectionPoint.is())
472 m_pImpl->m_XWeakConnectionPoint->removeReference(
473 (XReference*)m_pImpl);
474 m_pImpl->m_XWeakConnectionPoint.clear();
476 m_pImpl->release();
477 m_pImpl = 0;
480 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
483 WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
485 if (this == &rWeakRef)
487 return *this;
489 Reference< XInterface > xInt( rWeakRef.get() );
490 return operator = ( xInt );
493 WeakReferenceHelper & SAL_CALL
494 WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
495 SAL_THROW(())
499 clear();
500 if (xInt.is())
502 m_pImpl = new OWeakRefListener(xInt);
503 m_pImpl->acquire();
506 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
507 return *this;
510 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW(())
512 clear();
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;
526 if (xAdp.is())
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: */