Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <boost/noncopyable.hpp>
23 : #include <osl/mutex.hxx>
24 : #include <cppuhelper/weakagg.hxx>
25 : #include <cppuhelper/interfacecontainer.hxx>
26 : #include <cppuhelper/exc_hlp.hxx>
27 : #include <cppuhelper/queryinterface.hxx>
28 :
29 : using namespace osl;
30 : using namespace com::sun::star::uno;
31 :
32 : /** */ //for docpp
33 : namespace cppu
34 : {
35 :
36 : // due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
37 72982857 : inline static Mutex & getWeakMutex()
38 : {
39 : static Mutex * s_pMutex = 0;
40 72982857 : if (! s_pMutex)
41 506 : s_pMutex = new Mutex();
42 72982857 : return *s_pMutex;
43 : }
44 :
45 :
46 : //-- OWeakConnectionPoint ----------------------------------------------------
47 :
48 : class OWeakConnectionPoint: public XAdapter, private boost::noncopyable
49 : {
50 : public:
51 : /**
52 : Hold the weak object without an acquire (only the pointer).
53 : */
54 1750683 : explicit OWeakConnectionPoint( OWeakObject* pObj )
55 : : m_aRefCount( 0 )
56 : , m_pObject(pObj)
57 1750683 : , m_aReferences( getWeakMutex() )
58 1750683 : {}
59 :
60 : // XInterface
61 : Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
62 : void SAL_CALL acquire() throw() SAL_OVERRIDE;
63 : void SAL_CALL release() throw() SAL_OVERRIDE;
64 :
65 : // XAdapter
66 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
67 : void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
68 : void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
69 :
70 : /// Called from the weak object if the reference count goes to zero.
71 : void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
72 :
73 : private:
74 3492536 : virtual ~OWeakConnectionPoint() {}
75 :
76 : /// The reference counter.
77 : oslInterlockedCount m_aRefCount;
78 : /// The weak object
79 : OWeakObject* m_pObject;
80 : /// The container to hold the weak references
81 : OInterfaceContainerHelper m_aReferences;
82 : };
83 :
84 : // XInterface
85 9 : Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
86 : throw(com::sun::star::uno::RuntimeException, std::exception)
87 : {
88 : return ::cppu::queryInterface(
89 9 : rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
90 : }
91 :
92 : // XInterface
93 28969954 : void SAL_CALL OWeakConnectionPoint::acquire() throw()
94 : {
95 28969954 : osl_atomic_increment( &m_aRefCount );
96 28969954 : }
97 :
98 : // XInterface
99 28959246 : void SAL_CALL OWeakConnectionPoint::release() throw()
100 : {
101 28959246 : if (! osl_atomic_decrement( &m_aRefCount ))
102 1746268 : delete this;
103 28959246 : }
104 :
105 1746268 : void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
106 : {
107 1746268 : Any ex;
108 3492536 : OInterfaceIteratorHelper aIt( m_aReferences );
109 5228053 : while( aIt.hasMoreElements() )
110 : {
111 : try
112 : {
113 1735517 : static_cast<XReference *>(aIt.next())->dispose();
114 : }
115 0 : catch (com::sun::star::lang::DisposedException &) {}
116 0 : catch (RuntimeException &)
117 : {
118 0 : ex = cppu::getCaughtException();
119 : }
120 : }
121 1746268 : if (ex.hasValue())
122 : {
123 0 : cppu::throwException(ex);
124 1746268 : }
125 1746268 : }
126 :
127 : // XInterface
128 12697493 : Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException, std::exception)
129 : {
130 12697493 : Reference< XInterface > ret;
131 :
132 25394986 : ClearableMutexGuard guard(getWeakMutex());
133 :
134 12697493 : if (m_pObject)
135 : {
136 12697493 : oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
137 :
138 12697493 : if (n > 1)
139 : {
140 : // The refence is incremented. The object cannot be destroyed.
141 : // Release the guard at the earliest point.
142 12611293 : guard.clear();
143 : // WeakObject has a (XInterface *) cast operator
144 12611293 : ret = *m_pObject;
145 12611293 : n = osl_atomic_decrement( &m_pObject->m_refCount );
146 : }
147 : else
148 : // Another thread wait in the dispose method at the guard
149 86200 : n = osl_atomic_decrement( &m_pObject->m_refCount );
150 : }
151 :
152 25394986 : return ret;
153 : }
154 :
155 : // XInterface
156 6393169 : void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
157 : throw(::com::sun::star::uno::RuntimeException, std::exception)
158 : {
159 6393169 : m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
160 6393169 : }
161 :
162 : // XInterface
163 6386876 : void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
164 : throw(::com::sun::star::uno::RuntimeException, std::exception)
165 : {
166 6386876 : m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
167 6386876 : }
168 :
169 :
170 :
171 : //-- OWeakObject -------------------------------------------------------
172 :
173 :
174 : #ifdef _MSC_VER
175 : // Accidentally occurs in msvc mapfile = > had to be outlined.
176 : OWeakObject::OWeakObject()
177 : : m_refCount( 0 ),
178 : m_pWeakConnectionPoint( 0 )
179 : {
180 : }
181 : #endif
182 :
183 : // XInterface
184 123475937 : Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
185 : {
186 : return ::cppu::queryInterface(
187 : rType,
188 123475937 : static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
189 : }
190 :
191 : // XInterface
192 7841085037 : void SAL_CALL OWeakObject::acquire() throw()
193 : {
194 7841085037 : osl_atomic_increment( &m_refCount );
195 7841085037 : }
196 :
197 : // XInterface
198 6428416677 : void SAL_CALL OWeakObject::release() throw()
199 : {
200 6428416677 : if (osl_atomic_decrement( &m_refCount ) == 0) {
201 : // notify/clear all weak-refs before object's dtor is executed
202 : // (which may check weak-refs to this object):
203 104043666 : disposeWeakConnectionPoint();
204 : // destroy object:
205 104043667 : delete this;
206 : }
207 6428416679 : }
208 :
209 105264133 : void OWeakObject::disposeWeakConnectionPoint()
210 : {
211 : OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
212 105264133 : if (m_pWeakConnectionPoint != 0) {
213 1746268 : OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
214 1746268 : m_pWeakConnectionPoint = 0;
215 : try {
216 1746268 : p->dispose();
217 : }
218 0 : catch (RuntimeException const& exc) {
219 : OSL_FAIL(
220 : OUStringToOString(
221 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
222 : static_cast<void>(exc);
223 : }
224 1746268 : p->release();
225 : }
226 105264133 : }
227 :
228 104524741 : OWeakObject::~OWeakObject()
229 : {
230 104524737 : }
231 :
232 : // XWeak
233 6393169 : Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
234 : throw (::com::sun::star::uno::RuntimeException, std::exception)
235 : {
236 6393169 : if (!m_pWeakConnectionPoint)
237 : {
238 : // only acquire mutex if member is not created
239 1750683 : MutexGuard aGuard( getWeakMutex() );
240 1750683 : if( !m_pWeakConnectionPoint )
241 : {
242 1750683 : OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
243 1750683 : p->acquire();
244 1750683 : m_pWeakConnectionPoint = p;
245 1750683 : }
246 : }
247 :
248 6393169 : return m_pWeakConnectionPoint;
249 : }
250 :
251 :
252 : //-- OWeakAggObject ----------------------------------------------------
253 :
254 449713 : OWeakAggObject::~OWeakAggObject()
255 : {
256 449713 : }
257 :
258 : // XInterface
259 18909425 : void OWeakAggObject::acquire() throw()
260 : {
261 18909425 : Reference<XInterface > x( xDelegator );
262 18909430 : if (x.is())
263 1356943 : x->acquire();
264 : else
265 17552487 : OWeakObject::acquire();
266 18909431 : }
267 :
268 : // XInterface
269 18506771 : void OWeakAggObject::release() throw()
270 : {
271 18506771 : Reference<XInterface > x( xDelegator );
272 18506776 : if (x.is())
273 1356751 : x->release();
274 : else
275 17150026 : OWeakObject::release();
276 18506778 : }
277 :
278 : // XInterface
279 3719069 : Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
280 : {
281 3719069 : Reference< XInterface > x( xDelegator ); // harden ref
282 3719069 : return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
283 : }
284 :
285 : // XAggregation
286 1879592 : Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
287 : {
288 : return ::cppu::queryInterface(
289 : rType,
290 : static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
291 : static_cast< XAggregation * >( this ),
292 1879592 : static_cast< XWeak * >( this ) );
293 : }
294 :
295 : // XAggregation
296 32830 : void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException, std::exception)
297 : {
298 32830 : xDelegator = rDelegator;
299 32830 : }
300 :
301 : }
302 :
303 : /** */ //for docpp
304 : namespace com
305 : {
306 : /** */ //for docpp
307 : namespace sun
308 : {
309 : /** */ //for docpp
310 : namespace star
311 : {
312 : /** */ //for docpp
313 : namespace uno
314 : {
315 :
316 :
317 :
318 : //-- OWeakRefListener -----------------------------------------------------
319 :
320 : class OWeakRefListener: public XReference, private boost::noncopyable
321 : {
322 : public:
323 : explicit OWeakRefListener(const Reference< XInterface >& xInt);
324 : virtual ~OWeakRefListener();
325 :
326 : // XInterface
327 : Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
328 : void SAL_CALL acquire() throw() SAL_OVERRIDE;
329 : void SAL_CALL release() throw() SAL_OVERRIDE;
330 :
331 : // XReference
332 : void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
333 :
334 : /// The reference counter.
335 : oslInterlockedCount m_aRefCount;
336 : /// The connection point of the weak object
337 : Reference< XAdapter > m_XWeakConnectionPoint;
338 : };
339 :
340 6393169 : OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt)
341 6393169 : : m_aRefCount( 1 )
342 : {
343 : try
344 : {
345 6393169 : Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
346 :
347 6393169 : if (xWeak.is())
348 : {
349 6393169 : m_XWeakConnectionPoint = xWeak->queryAdapter();
350 :
351 6393169 : if (m_XWeakConnectionPoint.is())
352 : {
353 6393169 : m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
354 : }
355 6393169 : }
356 : }
357 0 : catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
358 6393169 : osl_atomic_decrement( &m_aRefCount );
359 6393169 : }
360 :
361 19150752 : OWeakRefListener::~OWeakRefListener()
362 : {
363 : try
364 : {
365 6383584 : if (m_XWeakConnectionPoint.is())
366 : {
367 0 : acquire(); // dont die again
368 0 : m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
369 : }
370 : }
371 0 : catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
372 12767168 : }
373 :
374 : // XInterface
375 34 : Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
376 : {
377 : return ::cppu::queryInterface(
378 34 : rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
379 : }
380 :
381 : // XInterface
382 42027648 : void SAL_CALL OWeakRefListener::acquire() throw()
383 : {
384 42027648 : osl_atomic_increment( &m_aRefCount );
385 42027648 : }
386 :
387 : // XInterface
388 42011769 : void SAL_CALL OWeakRefListener::release() throw()
389 : {
390 42011769 : if( ! osl_atomic_decrement( &m_aRefCount ) )
391 6383584 : delete this;
392 42011769 : }
393 :
394 1735517 : void SAL_CALL OWeakRefListener::dispose()
395 : throw(::com::sun::star::uno::RuntimeException, std::exception)
396 : {
397 1735517 : Reference< XAdapter > xAdp;
398 : {
399 1735517 : MutexGuard guard(cppu::getWeakMutex());
400 1735517 : if( m_XWeakConnectionPoint.is() )
401 : {
402 1735517 : xAdp = m_XWeakConnectionPoint;
403 1735517 : m_XWeakConnectionPoint.clear();
404 1735517 : }
405 : }
406 :
407 1735517 : if( xAdp.is() )
408 1735517 : xAdp->removeReference(static_cast<XReference*>(this));
409 1735517 : }
410 :
411 :
412 : //-- WeakReferenceHelper ----------------------------------------------------------
413 :
414 1504745 : WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt)
415 1504745 : : m_pImpl( 0 )
416 : {
417 1504745 : if (xInt.is())
418 : {
419 1502334 : m_pImpl = new OWeakRefListener(xInt);
420 1502334 : m_pImpl->acquire();
421 : }
422 1504745 : }
423 :
424 4385157 : WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef)
425 4385157 : : m_pImpl( 0 )
426 : {
427 4385157 : Reference< XInterface > xInt( rWeakRef.get() );
428 4385157 : if (xInt.is())
429 : {
430 4280539 : m_pImpl = new OWeakRefListener(xInt);
431 4280539 : m_pImpl->acquire();
432 4385157 : }
433 4385157 : }
434 :
435 8685765 : void WeakReferenceHelper::clear()
436 : {
437 : try
438 : {
439 8685765 : if (m_pImpl)
440 : {
441 6383584 : if (m_pImpl->m_XWeakConnectionPoint.is())
442 : {
443 4651359 : m_pImpl->m_XWeakConnectionPoint->removeReference(
444 4651359 : static_cast<XReference*>(m_pImpl));
445 4651359 : m_pImpl->m_XWeakConnectionPoint.clear();
446 : }
447 6383584 : m_pImpl->release();
448 6383584 : m_pImpl = 0;
449 : }
450 : }
451 0 : catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
452 8685765 : }
453 :
454 33292 : WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef)
455 : {
456 33292 : if (this == &rWeakRef)
457 : {
458 4 : return *this;
459 : }
460 33288 : Reference< XInterface > xInt( rWeakRef.get() );
461 33288 : return operator = ( xInt );
462 : }
463 :
464 : WeakReferenceHelper & SAL_CALL
465 717901 : WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
466 : {
467 : try
468 : {
469 717901 : clear();
470 717901 : if (xInt.is())
471 : {
472 610296 : m_pImpl = new OWeakRefListener(xInt);
473 610296 : m_pImpl->acquire();
474 : }
475 : }
476 0 : catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
477 717901 : return *this;
478 : }
479 :
480 7957981 : WeakReferenceHelper::~WeakReferenceHelper()
481 : {
482 7957981 : clear();
483 7957981 : }
484 :
485 55048509 : Reference< XInterface > WeakReferenceHelper::get() const
486 : {
487 : try
488 : {
489 55048509 : Reference< XAdapter > xAdp;
490 : {
491 55048496 : MutexGuard guard(cppu::getWeakMutex());
492 55048555 : if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
493 12697493 : xAdp = m_pImpl->m_XWeakConnectionPoint;
494 : }
495 :
496 55048541 : if (xAdp.is())
497 12697493 : return xAdp->queryAdapted();
498 : }
499 0 : catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
500 :
501 42351055 : return Reference< XInterface >();
502 : }
503 :
504 : }
505 : }
506 : }
507 : }
508 :
509 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|