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