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