1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppuhelper.hxx"
26 #include <osl/mutex.hxx>
27 #ifndef _CPPU_WEAKAGG_HXX_
28 #include <cppuhelper/weakagg.hxx>
29 #endif
30 #ifndef _CPPU_HELPER_INTERFACECONTAINER_HXX_
31 #include <cppuhelper/interfacecontainer.hxx>
32 #endif
33 #include "cppuhelper/exc_hlp.hxx"
34
35 using namespace osl;
36 using namespace com::sun::star::uno;
37
38 /** */ //for docpp
39 namespace cppu
40 {
41
42 // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#)
getWeakMutex()43 inline static Mutex & getWeakMutex() SAL_THROW( () )
44 {
45 static Mutex * s_pMutex = 0;
46 if (! s_pMutex)
47 s_pMutex = new Mutex();
48 return *s_pMutex;
49 }
50
51 //------------------------------------------------------------------------
52 //-- OWeakConnectionPoint ----------------------------------------------------
53 //------------------------------------------------------------------------
54 class OWeakConnectionPoint : public XAdapter
55 {
56 public:
57 /**
58 Hold the weak object without an acquire (only the pointer).
59 */
60 OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW( () )
61 : m_aRefCount( 0 )
62 , m_pObject(pObj)
63 , m_aReferences( getWeakMutex() )
64 {}
65
66 // XInterface
67 Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
68 void SAL_CALL acquire() throw();
69 void SAL_CALL release() throw();
70
71 // XAdapter
72 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException);
73 void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
74 void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
75
76 /// Called from the weak object if the reference count goes to zero.
77 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
78
79 private:
80 OWeakConnectionPoint(OWeakConnectionPoint &); // not defined
81 void operator =(OWeakConnectionPoint &); // not defined
82
~OWeakConnectionPoint()83 virtual ~OWeakConnectionPoint() {}
84
85 /// The reference counter.
86 oslInterlockedCount m_aRefCount;
87 /// The weak object
88 OWeakObject* m_pObject;
89 /// The container to hold the weak references
90 OInterfaceContainerHelper m_aReferences;
91 };
92
93 // XInterface
queryInterface(const Type & rType)94 Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
95 throw(com::sun::star::uno::RuntimeException)
96 {
97 return ::cppu::queryInterface(
98 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
99 }
100
101 // XInterface
acquire()102 void SAL_CALL OWeakConnectionPoint::acquire() throw()
103 {
104 osl_incrementInterlockedCount( &m_aRefCount );
105 }
106
107 // XInterface
release()108 void SAL_CALL OWeakConnectionPoint::release() throw()
109 {
110 if (! osl_decrementInterlockedCount( &m_aRefCount ))
111 delete this;
112 }
113
dispose()114 void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
115 {
116 Any ex;
117 OInterfaceIteratorHelper aIt( m_aReferences );
118 while( aIt.hasMoreElements() )
119 {
120 try
121 {
122 ((XReference *)aIt.next())->dispose();
123 }
124 catch (com::sun::star::lang::DisposedException &) {}
125 catch (RuntimeException &)
126 {
127 ex = cppu::getCaughtException();
128 }
129 }
130 if (ex.hasValue())
131 {
132 cppu::throwException(ex);
133 }
134 }
135
136 // XInterface
queryAdapted()137 Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException)
138 {
139 Reference< XInterface > ret;
140
141 ClearableMutexGuard guard(getWeakMutex());
142
143 if (m_pObject)
144 {
145 oslInterlockedCount n = osl_incrementInterlockedCount( &m_pObject->m_refCount );
146
147 if (n > 1)
148 {
149 // The refence is incremented. The object cannot be destroyed.
150 // Release the guard at the earliest point.
151 guard.clear();
152 // WeakObject has a (XInterface *) cast operator
153 ret = *m_pObject;
154 n = osl_decrementInterlockedCount( &m_pObject->m_refCount );
155 }
156 else
157 // Another thread wait in the dispose method at the guard
158 n = osl_decrementInterlockedCount( &m_pObject->m_refCount );
159 }
160
161 return ret;
162 }
163
164 // XInterface
addReference(const Reference<XReference> & rRef)165 void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
166 throw(::com::sun::star::uno::RuntimeException)
167 {
168 m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
169 }
170
171 // XInterface
removeReference(const Reference<XReference> & rRef)172 void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
173 throw(::com::sun::star::uno::RuntimeException)
174 {
175 m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
176 }
177
178
179 //------------------------------------------------------------------------
180 //-- OWeakObject -------------------------------------------------------
181 //------------------------------------------------------------------------
182
183 #ifdef _MSC_VER
184 // Accidentally occurs in msvc mapfile = > had to be outlined.
OWeakObject()185 OWeakObject::OWeakObject() SAL_THROW( () )
186 : m_refCount( 0 ),
187 m_pWeakConnectionPoint( 0 )
188 {
189 }
190 #endif
191
192 // XInterface
queryInterface(const Type & rType)193 Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
194 {
195 return ::cppu::queryInterface(
196 rType,
197 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
198 }
199
200 // XInterface
acquire()201 void SAL_CALL OWeakObject::acquire() throw()
202 {
203 osl_incrementInterlockedCount( &m_refCount );
204 }
205
206 // XInterface
release()207 void SAL_CALL OWeakObject::release() throw()
208 {
209 if (osl_decrementInterlockedCount( &m_refCount ) == 0) {
210 // notify/clear all weak-refs before object's dtor is executed
211 // (which may check weak-refs to this object):
212 disposeWeakConnectionPoint();
213 // destroy object:
214 delete this;
215 }
216 }
217
disposeWeakConnectionPoint()218 void OWeakObject::disposeWeakConnectionPoint()
219 {
220 OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
221 if (m_pWeakConnectionPoint != 0) {
222 OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
223 m_pWeakConnectionPoint = 0;
224 try {
225 p->dispose();
226 }
227 catch (RuntimeException const& exc) {
228 OSL_ENSURE(
229 false, OUStringToOString(
230 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
231 static_cast<void>(exc);
232 }
233 p->release();
234 }
235 }
236
~OWeakObject()237 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) )
238 {
239 }
240
241 // XWeak
queryAdapter()242 Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
243 throw (::com::sun::star::uno::RuntimeException)
244 {
245 if (!m_pWeakConnectionPoint)
246 {
247 // only acquire mutex if member is not created
248 MutexGuard aGuard( getWeakMutex() );
249 if( !m_pWeakConnectionPoint )
250 {
251 OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
252 p->acquire();
253 m_pWeakConnectionPoint = p;
254 }
255 }
256
257 return m_pWeakConnectionPoint;
258 }
259
260 //------------------------------------------------------------------------
261 //-- OWeakAggObject ----------------------------------------------------
262 //------------------------------------------------------------------------
~OWeakAggObject()263 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) )
264 {
265 }
266
267 // XInterface
acquire()268 void OWeakAggObject::acquire() throw()
269 {
270 Reference<XInterface > x( xDelegator );
271 if (x.is())
272 x->acquire();
273 else
274 OWeakObject::acquire();
275 }
276
277 // XInterface
release()278 void OWeakAggObject::release() throw()
279 {
280 Reference<XInterface > x( xDelegator );
281 if (x.is())
282 x->release();
283 else
284 OWeakObject::release();
285 }
286
287 // XInterface
queryInterface(const Type & rType)288 Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
289 {
290 Reference< XInterface > x( xDelegator ); // harden ref
291 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
292
293 // // set rOut to zero, if failed
294 // if( !xDelegator.queryHardRef( aUik, rOut ) )
295 // {
296 // XInterfaceRef x;
297 // if( !xDelegator.queryHardRef( ((XInterface*)0)->getSmartUik(), x ) )
298 // // reference is not valid
299 // queryAggregation( aUik, rOut );
300 // }
301 // return rOut.is();
302 }
303
304 // XAggregation
queryAggregation(const Type & rType)305 Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
306 {
307 return ::cppu::queryInterface(
308 rType,
309 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
310 static_cast< XAggregation * >( this ),
311 static_cast< XWeak * >( this ) );
312 }
313
314 // XAggregation
setDelegator(const Reference<XInterface> & rDelegator)315 void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException)
316 {
317 xDelegator = rDelegator;
318 }
319
320 }
321
322 /** */ //for docpp
323 namespace com
324 {
325 /** */ //for docpp
326 namespace sun
327 {
328 /** */ //for docpp
329 namespace star
330 {
331 /** */ //for docpp
332 namespace uno
333 {
334
335
336 //------------------------------------------------------------------------
337 //-- OWeakRefListener -----------------------------------------------------
338 //------------------------------------------------------------------------
339 class OWeakRefListener : public XReference
340 {
341 public:
342 OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () );
343 OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () );
344 virtual ~OWeakRefListener() SAL_THROW( () );
345
346 // XInterface
347 Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException);
348 void SAL_CALL acquire() throw();
349 void SAL_CALL release() throw();
350
351 // XReference
352 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
353
354 /// The reference counter.
355 oslInterlockedCount m_aRefCount;
356 /// The connection point of the weak object
357 Reference< XAdapter > m_XWeakConnectionPoint;
358
359 private:
360 OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW( () );
361 };
362
OWeakRefListener(const OWeakRefListener & rRef)363 OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () )
364 : com::sun::star::uno::XReference()
365 , m_aRefCount( 1 )
366 {
367 try
368 {
369 m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint;
370
371 if (m_XWeakConnectionPoint.is())
372 {
373 m_XWeakConnectionPoint->addReference((XReference*)this);
374 }
375 }
376 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
377 osl_decrementInterlockedCount( &m_aRefCount );
378 }
379
OWeakRefListener(const Reference<XInterface> & xInt)380 OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () )
381 : m_aRefCount( 1 )
382 {
383 try
384 {
385 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
386
387 if (xWeak.is())
388 {
389 m_XWeakConnectionPoint = xWeak->queryAdapter();
390
391 if (m_XWeakConnectionPoint.is())
392 {
393 m_XWeakConnectionPoint->addReference((XReference*)this);
394 }
395 }
396 }
397 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
398 osl_decrementInterlockedCount( &m_aRefCount );
399 }
400
~OWeakRefListener()401 OWeakRefListener::~OWeakRefListener() SAL_THROW( () )
402 {
403 try
404 {
405 if (m_XWeakConnectionPoint.is())
406 {
407 acquire(); // don't die again
408 m_XWeakConnectionPoint->removeReference((XReference*)this);
409 }
410 }
411 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
412 }
413
414 // XInterface
queryInterface(const Type & rType)415 Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException)
416 {
417 return ::cppu::queryInterface(
418 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
419 }
420
421 // XInterface
acquire()422 void SAL_CALL OWeakRefListener::acquire() throw()
423 {
424 osl_incrementInterlockedCount( &m_aRefCount );
425 }
426
427 // XInterface
release()428 void SAL_CALL OWeakRefListener::release() throw()
429 {
430 if( ! osl_decrementInterlockedCount( &m_aRefCount ) )
431 delete this;
432 }
433
dispose()434 void SAL_CALL OWeakRefListener::dispose()
435 throw(::com::sun::star::uno::RuntimeException)
436 {
437 Reference< XAdapter > xAdp;
438 {
439 MutexGuard guard(cppu::getWeakMutex());
440 if( m_XWeakConnectionPoint.is() )
441 {
442 xAdp = m_XWeakConnectionPoint;
443 m_XWeakConnectionPoint.clear();
444 }
445 }
446
447 if( xAdp.is() )
448 xAdp->removeReference((XReference*)this);
449 }
450
451 //------------------------------------------------------------------------
452 //-- WeakReferenceHelper ----------------------------------------------------------
453 //------------------------------------------------------------------------
WeakReferenceHelper(const Reference<XInterface> & xInt)454 WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW( () )
455 : m_pImpl( 0 )
456 {
457 if (xInt.is())
458 {
459 m_pImpl = new OWeakRefListener(xInt);
460 m_pImpl->acquire();
461 }
462 }
463
WeakReferenceHelper(const WeakReferenceHelper & rWeakRef)464 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW( () )
465 : m_pImpl( 0 )
466 {
467 Reference< XInterface > xInt( rWeakRef.get() );
468 if (xInt.is())
469 {
470 m_pImpl = new OWeakRefListener(xInt);
471 m_pImpl->acquire();
472 }
473 }
474
clear()475 void WeakReferenceHelper::clear() SAL_THROW( () )
476 {
477 try
478 {
479 if (m_pImpl)
480 {
481 if (m_pImpl->m_XWeakConnectionPoint.is())
482 {
483 m_pImpl->m_XWeakConnectionPoint->removeReference(
484 (XReference*)m_pImpl);
485 m_pImpl->m_XWeakConnectionPoint.clear();
486 }
487 m_pImpl->release();
488 m_pImpl = 0;
489 }
490 }
491 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
492 }
493
operator =(const WeakReferenceHelper & rWeakRef)494 WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW( () )
495 {
496 if (this == &rWeakRef)
497 {
498 return *this;
499 }
500 Reference< XInterface > xInt( rWeakRef.get() );
501 return operator = ( xInt );
502 }
503
504 WeakReferenceHelper & SAL_CALL
operator =(const Reference<XInterface> & xInt)505 WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
506 SAL_THROW( () )
507 {
508 try
509 {
510 clear();
511 if (xInt.is())
512 {
513 m_pImpl = new OWeakRefListener(xInt);
514 m_pImpl->acquire();
515 }
516 }
517 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
518 return *this;
519 }
520
~WeakReferenceHelper()521 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW( () )
522 {
523 clear();
524 }
525
get() const526 Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW( () )
527 {
528 try
529 {
530 Reference< XAdapter > xAdp;
531 {
532 MutexGuard guard(cppu::getWeakMutex());
533 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
534 xAdp = m_pImpl->m_XWeakConnectionPoint;
535 }
536
537 if (xAdp.is())
538 return xAdp->queryAdapted();
539 }
540 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
541
542 return Reference< XInterface >();
543 }
544
545 }
546 }
547 }
548 }
549
550