LibreOffice Module cppuhelper (master) 1
weak.cxx
Go to the documentation of this file.
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#include <sal/log.hxx>
22
23#include <osl/diagnose.h>
27
28#include <com/sun/star/lang/DisposedException.hpp>
29
30#include <algorithm>
31#include <vector>
32#include <mutex>
33
34using namespace osl;
35using namespace com::sun::star::uno;
36
37namespace cppu
38{
39
40// due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
41// this is used to lock all instances of OWeakConnectionPoint and OWeakRefListener as well as OWeakObject::m_pWeakConnectionPoint
42static std::mutex * gpWeakMutex = new std::mutex;
43
44
45//-- OWeakConnectionPoint ----------------------------------------------------
46
47class OWeakConnectionPoint: public XAdapter
48{
49public:
54 : m_aRefCount( 0 )
55 , m_pObject(pObj)
56 {}
57
58 // noncopyable
61
62 // XInterface
63 Any SAL_CALL queryInterface( const Type & rType ) override;
64 void SAL_CALL acquire() noexcept override;
65 void SAL_CALL release() noexcept override;
66
67 // XAdapter
68 css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override;
69 void SAL_CALL addReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
70 void SAL_CALL removeReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
71
75 void dispose();
76
77private:
79
81 oslInterlockedCount m_aRefCount;
85 std::vector<Reference<XReference>> m_aReferences;
86};
87
88// XInterface
90{
92 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
93}
94
95// XInterface
96void SAL_CALL OWeakConnectionPoint::acquire() noexcept
97{
98#ifdef DBG_UTIL
99 // catch things early which have been deleted and then re-acquired
100 assert(m_aRefCount != -1);
101#endif
102 osl_atomic_increment( &m_aRefCount );
103}
104
105// XInterface
106void SAL_CALL OWeakConnectionPoint::release() noexcept
107{
108 if (! osl_atomic_decrement( &m_aRefCount ))
109 {
110#ifdef DBG_UTIL
111 m_aRefCount = -1;
112#endif
113 delete this;
114 }
115}
116
118{
119 std::vector<Reference<XReference>> aCopy;
120 { // only hold the mutex while we access the field
121 std::scoped_lock aGuard(*cppu::gpWeakMutex);
122 // OWeakObject is not the only owner of this, so clear m_pObject
123 // so that queryAdapted() won't use it now that it's dead
124 m_pObject = nullptr;
125 // other code is going to call removeReference while we are doing this, so we need a
126 // copy, but since we are disposing and going away, we can just take the original data
127 aCopy.swap(m_aReferences);
128 }
129 Any ex;
130 for (const Reference<XReference> & i : aCopy )
131 {
132 try
133 {
134 i->dispose();
135 }
136 catch (css::lang::DisposedException &) {}
137 catch (RuntimeException &)
138 {
140 }
141 }
142 if (ex.hasValue())
143 {
145 }
146}
147
148// XInterface
150{
152
153 {
154 std::scoped_lock guard(*gpWeakMutex);
155
156 if (!m_pObject)
157 return ret;
158
159 oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
160
161 if (n <= 1)
162 {
163 // Another thread wait in the dispose method at the guard
164 osl_atomic_decrement( &m_pObject->m_refCount );
165 return ret;
166 }
167 }
168
169 // n is now > 1
170 // The reference is incremented. The object cannot be destroyed.
171 // Release the guard at the earliest point.
172 // WeakObject has a (XInterface *) cast operator
173 ret = *m_pObject;
174 osl_atomic_decrement( &m_pObject->m_refCount );
175
176 return ret;
177}
178
179// XInterface
181{
182 std::scoped_lock aGuard(*gpWeakMutex);
183 m_aReferences.push_back( rRef );
184}
185
186// XInterface
188{
189 std::scoped_lock aGuard(*gpWeakMutex);
190 // Search from end because the thing that last added a ref is most likely to be the
191 // first to remove a ref.
192 // It's not really valid to compare the pointer directly, but it's faster.
193 auto it = std::find_if(m_aReferences.rbegin(), m_aReferences.rend(),
194 [&rRef](const Reference<XReference>& rxRef) { return rxRef.get() == rRef.get(); });
195 if (it != m_aReferences.rend()) {
196 m_aReferences.erase( it.base()-1 );
197 return;
198 }
199 // interface not found, use the correct compare method
200 it = std::find(m_aReferences.rbegin(), m_aReferences.rend(), rRef);
201 if ( it != m_aReferences.rend() )
202 m_aReferences.erase( it.base()-1 );
203}
204
205
206//-- OWeakObject -------------------------------------------------------
207
208// XInterface
209Any SAL_CALL OWeakObject::queryInterface( const Type & rType )
210{
212 rType,
213 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
214}
215
216// XInterface
217void SAL_CALL OWeakObject::acquire() noexcept
218{
219 osl_atomic_increment( &m_refCount );
220}
221
222// XInterface
223void SAL_CALL OWeakObject::release() noexcept
224{
225 if (osl_atomic_decrement( &m_refCount ) == 0) {
226 // notify/clear all weak-refs before object's dtor is executed
227 // (which may check weak-refs to this object):
229 // destroy object:
230 delete this;
231 }
232}
233
235{
236 OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
237 if (m_pWeakConnectionPoint != nullptr) {
238 OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
239 m_pWeakConnectionPoint = nullptr;
240 try {
241 p->dispose();
242 }
243 catch (RuntimeException const& exc) {
244 SAL_WARN( "cppuhelper", exc );
245 }
246 p->release();
247 }
248}
249
250OWeakObject::~OWeakObject() COVERITY_NOEXCEPT_FALSE
251{
252}
253
254// XWeak
256{
257 if (!m_pWeakConnectionPoint)
258 {
259 // only acquire mutex if member is not created
260 std::scoped_lock aGuard( *gpWeakMutex );
261 if( !m_pWeakConnectionPoint )
262 {
264 p->acquire();
265 m_pWeakConnectionPoint = p;
266 }
267 }
268
269 return m_pWeakConnectionPoint;
270}
271
272
273//-- OWeakAggObject ----------------------------------------------------
274
276{
277}
278
279// XInterface
281{
283 if (x.is())
284 x->acquire();
285 else
287}
288
289// XInterface
291{
293 if (x.is())
294 x->release();
295 else
297}
298
299// XInterface
301{
302 Reference< XInterface > x( xDelegator ); // harden ref
303 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
304}
305
306// XAggregation
308{
310 rType,
311 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
312 static_cast< XAggregation * >( this ),
313 static_cast< XWeak * >( this ) );
314}
315
316// XAggregation
318{
319 xDelegator = rDelegator;
320}
321
322}
323
324namespace com::sun::star::uno
325{
326
327
328//-- OWeakRefListener -----------------------------------------------------
329
330class OWeakRefListener final : public XReference
331{
332public:
333 explicit OWeakRefListener(const Reference< XInterface >& xInt);
334 explicit OWeakRefListener(const Reference< XWeak >& xInt);
335 virtual ~OWeakRefListener();
336
337 // noncopyable
340
341 // XInterface
342 Any SAL_CALL queryInterface( const Type & rType ) override;
343 void SAL_CALL acquire() noexcept override;
344 void SAL_CALL release() noexcept override;
345
346 // XReference
347 void SAL_CALL dispose() override;
348
350 oslInterlockedCount m_aRefCount;
353};
354
356 : m_aRefCount( 1 )
357{
358 try
359 {
361
362 if (xWeak.is())
363 {
364 m_XWeakConnectionPoint = xWeak->queryAdapter();
365
366 if (m_XWeakConnectionPoint.is())
367 {
368 m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
369 }
370 }
371 }
372 catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
373 osl_atomic_decrement( &m_aRefCount );
374}
375
377 : m_aRefCount( 1 )
378{
379 m_XWeakConnectionPoint = xWeak->queryAdapter();
380
381 if (m_XWeakConnectionPoint.is())
382 {
383 m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
384 }
385 osl_atomic_decrement( &m_aRefCount );
386}
387
389{
390 try
391 {
392 if (m_XWeakConnectionPoint.is())
393 {
394 acquire(); // don't die again
395 m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
396 }
397 }
398 catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
399}
400
401// XInterface
403{
405 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
406}
407
408// XInterface
409void SAL_CALL OWeakRefListener::acquire() noexcept
410{
411 osl_atomic_increment( &m_aRefCount );
412}
413
414// XInterface
415void SAL_CALL OWeakRefListener::release() noexcept
416{
417 if( ! osl_atomic_decrement( &m_aRefCount ) )
418 delete this;
419}
420
422{
424 {
425 std::scoped_lock guard(*cppu::gpWeakMutex);
426 if( m_XWeakConnectionPoint.is() )
427 {
430 }
431 }
432
433 if( xAdp.is() )
434 xAdp->removeReference(static_cast<XReference*>(this));
435}
436
437
438//-- WeakReferenceHelper ----------------------------------------------------------
439
441 : m_pImpl( nullptr )
442{
443 if (xInt.is())
444 {
445 m_pImpl = new OWeakRefListener(xInt);
446 m_pImpl->acquire();
447 }
448}
449
451 : m_pImpl( nullptr )
452{
453 if (xWeak.is())
454 {
455 m_pImpl = new OWeakRefListener(xWeak);
456 m_pImpl->acquire();
457 }
458}
459
461 : m_pImpl( nullptr )
462{
463 Reference< XInterface > xInt( rWeakRef.get() );
464 if (xInt.is())
465 {
466 m_pImpl = new OWeakRefListener(xInt);
467 m_pImpl->acquire();
468 }
469}
470
472{
473 try
474 {
475 if (m_pImpl)
476 {
477 m_pImpl->dispose();
478 m_pImpl->release();
479 m_pImpl = nullptr;
480 }
481 }
482 catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
483}
484
486{
487 if (this == &rWeakRef)
488 {
489 return *this;
490 }
491 Reference< XInterface > xInt( rWeakRef.get() );
492 return operator = ( xInt );
493}
494
496 WeakReferenceHelper && other)
497{
498 clear();
499 std::swap(m_pImpl, other.m_pImpl);
500 return *this;
501}
502
503WeakReferenceHelper & SAL_CALL
505{
506 try
507 {
508 clear();
509 if (xInt.is())
510 {
511 m_pImpl = new OWeakRefListener(xInt);
512 m_pImpl->acquire();
513 }
514 }
515 catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
516 return *this;
517}
518
521{
522 clear();
523 if (xWeak)
524 {
525 m_pImpl = new OWeakRefListener(xWeak);
526 m_pImpl->acquire();
527 }
528 return *this;
529}
530
532{
533 clear();
534}
535
537{
538 try
539 {
541 {
542 // must lock to access m_XWeakConnectionPoint
543 std::scoped_lock guard(*cppu::gpWeakMutex);
544 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
545 xAdp = m_pImpl->m_XWeakConnectionPoint;
546 }
547
548 if (xAdp.is())
549 return xAdp->queryAdapted();
550 }
551 catch (RuntimeException &)
552 {
553 OSL_ASSERT( false );
554 } // assert here, but no unexpected()
555
557}
558
559}
560
561/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
OWeakRefListener(const Reference< XInterface > &xInt)
Definition: weak.cxx:355
void SAL_CALL release() noexcept override
Definition: weak.cxx:415
Any SAL_CALL queryInterface(const Type &rType) override
Definition: weak.cxx:402
oslInterlockedCount m_aRefCount
The reference counter.
Definition: weak.cxx:350
OWeakRefListener(const OWeakRefListener &)=delete
Reference< XAdapter > m_XWeakConnectionPoint
The connection point of the weak object, guarded by getWeakMutex()
Definition: weak.cxx:352
const OWeakRefListener & operator=(const OWeakRefListener &)=delete
void SAL_CALL dispose() override
Definition: weak.cxx:421
void SAL_CALL acquire() noexcept override
Definition: weak.cxx:409
The WeakReferenceHelper holds a weak reference to an object.
Definition: weakref.hxx:57
~WeakReferenceHelper()
Releases this reference.
Definition: weak.cxx:531
WeakReferenceHelper &SAL_CALL operator=(const WeakReferenceHelper &rWeakRef)
Releases this reference and takes over rWeakRef.
Definition: weak.cxx:485
void SAL_CALL clear()
Releases this reference.
Definition: weak.cxx:471
css::uno::Reference< css::uno::XInterface > SAL_CALL get() const
Gets a hard reference to the object.
Definition: weak.cxx:536
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &rType) SAL_OVERRIDE
Called by the delegator or queryInterface.
Definition: weak.cxx:307
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) SAL_OVERRIDE
If a delegator is set, then the delegator is queried for the demanded interface.
Definition: weak.cxx:300
css::uno::WeakReferenceHelper xDelegator
weak reference to delegator.
Definition: weakagg.hxx:96
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
If a delegator is set, then the delegators gets acquired.
Definition: weak.cxx:280
virtual void SAL_CALL setDelegator(const css::uno::Reference< css::uno::XInterface > &Delegator) SAL_OVERRIDE
Set the delegator.
Definition: weak.cxx:317
virtual ~OWeakAggObject() SAL_OVERRIDE
Virtual dtor.
Definition: weak.cxx:275
virtual void SAL_CALL release() SAL_NOEXCEPT SAL_OVERRIDE
If a delegator is set, then the delegators gets released.
Definition: weak.cxx:290
oslInterlockedCount m_aRefCount
The reference counter.
Definition: weak.cxx:81
void SAL_CALL removeReference(const css::uno::Reference< css::uno::XReference > &xRef) override
Definition: weak.cxx:187
OWeakConnectionPoint(const OWeakConnectionPoint &)=delete
OWeakObject * m_pObject
The weak object.
Definition: weak.cxx:83
void SAL_CALL acquire() noexcept override
Definition: weak.cxx:96
void SAL_CALL addReference(const css::uno::Reference< css::uno::XReference > &xRef) override
Definition: weak.cxx:180
OWeakConnectionPoint(OWeakObject *pObj)
Hold the weak object without an acquire (only the pointer).
Definition: weak.cxx:53
Any SAL_CALL queryInterface(const Type &rType) override
Definition: weak.cxx:89
const OWeakConnectionPoint & operator=(const OWeakConnectionPoint &)=delete
std::vector< Reference< XReference > > m_aReferences
The container to hold the weak references.
Definition: weak.cxx:85
css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override
Definition: weak.cxx:149
void SAL_CALL release() noexcept override
Definition: weak.cxx:106
void dispose()
Called from the weak object if the reference count goes to zero.
Definition: weak.cxx:117
Base class to implement a UNO object supporting weak references, i.e.
Definition: weak.hxx:48
virtual ~OWeakObject() COVERITY_NOEXCEPT_FALSE
Virtual dtor.
Definition: weak.cxx:250
oslInterlockedCount m_refCount
reference count.
Definition: weak.hxx:71
void disposeWeakConnectionPoint()
disposes and resets m_pWeakConnectionPoint
Definition: weak.cxx:234
virtual css::uno::Reference< css::uno::XAdapter > SAL_CALL queryAdapter() SAL_OVERRIDE
XWeak::queryAdapter() implementation.
Definition: weak.cxx:255
friend class OWeakConnectionPoint
Definition: weak.hxx:49
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
increasing m_refCount
Definition: weak.cxx:217
virtual void SAL_CALL release() SAL_NOEXCEPT SAL_OVERRIDE
decreasing m_refCount
Definition: weak.cxx:223
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) SAL_OVERRIDE
Basic queryInterface() implementation supporting com::sun::star::uno::XWeak and com::sun::star::uno::...
Definition: weak.cxx:209
float x
void * p
sal_Int64 n
#define SAL_WARN(area, stream)
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
Compares demanded type to given template argument types.
void SAL_CALL throwException(Any const &exc)
Any SAL_CALL getCaughtException()
Use this function to get the dynamic type of a caught C++-UNO exception; completes the above function...
static std::mutex * gpWeakMutex
Definition: weak.cxx:42
int i