File: | home/maarten/src/libreoffice/core/include/com/sun/star/uno/Reference.hxx |
Warning: | line 109, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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> | |||
24 | #include <osl/mutex.hxx> | |||
25 | #include <cppuhelper/weakagg.hxx> | |||
26 | #include <cppuhelper/exc_hlp.hxx> | |||
27 | #include <cppuhelper/queryinterface.hxx> | |||
28 | ||||
29 | #include <com/sun/star/lang/DisposedException.hpp> | |||
30 | ||||
31 | #include <algorithm> | |||
32 | #include <vector> | |||
33 | ||||
34 | using namespace osl; | |||
35 | using namespace com::sun::star::uno; | |||
36 | ||||
37 | /** */ //for docpp | |||
38 | namespace cppu | |||
39 | { | |||
40 | ||||
41 | // due to static Reflection destruction from usr, there must be a mutex leak (#73272#) | |||
42 | // this is used to lock all instances of OWeakConnectionPoint and OWeakRefListener as well as OWeakObject::m_pWeakConnectionPoint | |||
43 | static Mutex & getWeakMutex() | |||
44 | { | |||
45 | static Mutex * 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 | explicit OWeakConnectionPoint( OWeakObject* pObj ) | |||
59 | : m_aRefCount( 0 ) | |||
60 | , m_pObject(pObj) | |||
61 | {} | |||
62 | ||||
63 | // noncopyable | |||
64 | OWeakConnectionPoint(const OWeakConnectionPoint&) = delete; | |||
65 | const OWeakConnectionPoint& operator=(const OWeakConnectionPoint&) = delete; | |||
66 | ||||
67 | // XInterface | |||
68 | Any SAL_CALL queryInterface( const Type & rType ) override; | |||
69 | void SAL_CALL acquire() throw() override; | |||
70 | void SAL_CALL release() throw() override; | |||
71 | ||||
72 | // XAdapter | |||
73 | css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override; | |||
74 | void SAL_CALL addReference( const css::uno::Reference< css::uno::XReference >& xRef ) override; | |||
75 | void SAL_CALL removeReference( const css::uno::Reference< css::uno::XReference >& xRef ) override; | |||
76 | ||||
77 | /// Called from the weak object if the reference count goes to zero. | |||
78 | /// | |||
79 | /// @throws css::uno::RuntimeException | |||
80 | void dispose(); | |||
81 | ||||
82 | private: | |||
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 | std::vector<Reference<XReference>> m_aReferences; | |||
91 | }; | |||
92 | ||||
93 | // XInterface | |||
94 | Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType ) | |||
95 | { | |||
96 | return ::cppu::queryInterface( | |||
97 | rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) ); | |||
98 | } | |||
99 | ||||
100 | // XInterface | |||
101 | void SAL_CALL OWeakConnectionPoint::acquire() throw() | |||
102 | { | |||
103 | osl_atomic_increment( &m_aRefCount )__sync_add_and_fetch((&m_aRefCount), 1); | |||
104 | } | |||
105 | ||||
106 | // XInterface | |||
107 | void SAL_CALL OWeakConnectionPoint::release() throw() | |||
108 | { | |||
109 | if (! osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1)) | |||
110 | delete this; | |||
111 | } | |||
112 | ||||
113 | void OWeakConnectionPoint::dispose() | |||
114 | { | |||
115 | std::vector<Reference<XReference>> aCopy; | |||
116 | { // only hold the mutex while we access the field | |||
117 | MutexGuard aGuard(getWeakMutex()); | |||
118 | // OWeakObject is not the only owner of this, so clear m_pObject | |||
119 | // so that queryAdapted() won't use it now that it's dead | |||
120 | m_pObject = nullptr; | |||
121 | // other code is going to call removeReference while we are doing this, so we need a | |||
122 | // copy, but since we are disposing and going away, we can just take the original data | |||
123 | aCopy.swap(m_aReferences); | |||
124 | } | |||
125 | Any ex; | |||
126 | for (const Reference<XReference> & i : aCopy ) | |||
127 | { | |||
128 | try | |||
129 | { | |||
130 | i->dispose(); | |||
131 | } | |||
132 | catch (css::lang::DisposedException &) {} | |||
133 | catch (RuntimeException &) | |||
134 | { | |||
135 | ex = cppu::getCaughtException(); | |||
136 | } | |||
137 | } | |||
138 | if (ex.hasValue()) | |||
139 | { | |||
140 | cppu::throwException(ex); | |||
141 | } | |||
142 | } | |||
143 | ||||
144 | // XInterface | |||
145 | Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() | |||
146 | { | |||
147 | Reference< XInterface > ret; | |||
148 | ||||
149 | ClearableMutexGuard guard(getWeakMutex()); | |||
150 | ||||
151 | if (m_pObject) | |||
152 | { | |||
153 | oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount )__sync_add_and_fetch((&m_pObject->m_refCount), 1); | |||
154 | ||||
155 | if (n > 1) | |||
156 | { | |||
157 | // The reference is incremented. The object cannot be destroyed. | |||
158 | // Release the guard at the earliest point. | |||
159 | guard.clear(); | |||
160 | // WeakObject has a (XInterface *) cast operator | |||
161 | ret = *m_pObject; | |||
162 | osl_atomic_decrement( &m_pObject->m_refCount )__sync_sub_and_fetch((&m_pObject->m_refCount), 1); | |||
163 | } | |||
164 | else | |||
165 | // Another thread wait in the dispose method at the guard | |||
166 | osl_atomic_decrement( &m_pObject->m_refCount )__sync_sub_and_fetch((&m_pObject->m_refCount), 1); | |||
167 | } | |||
168 | ||||
169 | return ret; | |||
170 | } | |||
171 | ||||
172 | // XInterface | |||
173 | void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef) | |||
174 | { | |||
175 | MutexGuard aGuard(getWeakMutex()); | |||
176 | m_aReferences.push_back( rRef ); | |||
177 | } | |||
178 | ||||
179 | // XInterface | |||
180 | void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef) | |||
181 | { | |||
182 | MutexGuard aGuard(getWeakMutex()); | |||
183 | // Search from end because the thing that last added a ref is most likely to be the | |||
184 | // first to remove a ref. | |||
185 | // It's not really valid to compare the pointer directly, but it's faster. | |||
186 | auto it = std::find_if(m_aReferences.rbegin(), m_aReferences.rend(), | |||
187 | [&rRef](const Reference<XReference>& rxRef) { return rxRef.get() == rRef.get(); }); | |||
188 | if (it != m_aReferences.rend()) { | |||
189 | m_aReferences.erase( it.base()-1 ); | |||
190 | return; | |||
191 | } | |||
192 | // interface not found, use the correct compare method | |||
193 | it = std::find(m_aReferences.rbegin(), m_aReferences.rend(), rRef); | |||
194 | if ( it != m_aReferences.rend() ) | |||
195 | m_aReferences.erase( it.base()-1 ); | |||
196 | } | |||
197 | ||||
198 | ||||
199 | //-- OWeakObject ------------------------------------------------------- | |||
200 | ||||
201 | ||||
202 | #ifdef _MSC_VER | |||
203 | // Accidentally occurs in msvc mapfile = > had to be outlined. | |||
204 | OWeakObject::OWeakObject() | |||
205 | : m_refCount( 0 ), | |||
206 | m_pWeakConnectionPoint( nullptr ) | |||
207 | { | |||
208 | } | |||
209 | #endif | |||
210 | ||||
211 | // XInterface | |||
212 | Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) | |||
213 | { | |||
214 | return ::cppu::queryInterface( | |||
215 | rType, | |||
216 | static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) ); | |||
217 | } | |||
218 | ||||
219 | // XInterface | |||
220 | void SAL_CALL OWeakObject::acquire() throw() | |||
221 | { | |||
222 | osl_atomic_increment( &m_refCount )__sync_add_and_fetch((&m_refCount), 1); | |||
223 | } | |||
224 | ||||
225 | // XInterface | |||
226 | void SAL_CALL OWeakObject::release() throw() | |||
227 | { | |||
228 | if (osl_atomic_decrement( &m_refCount )__sync_sub_and_fetch((&m_refCount), 1) == 0) { | |||
229 | // notify/clear all weak-refs before object's dtor is executed | |||
230 | // (which may check weak-refs to this object): | |||
231 | disposeWeakConnectionPoint(); | |||
232 | // destroy object: | |||
233 | delete this; | |||
234 | } | |||
235 | } | |||
236 | ||||
237 | void OWeakObject::disposeWeakConnectionPoint() | |||
238 | { | |||
239 | OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" )do { if (true && (!(m_refCount == 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "239" ": "), "%s", "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" ); } } while (false); | |||
240 | if (m_pWeakConnectionPoint != nullptr) { | |||
241 | OWeakConnectionPoint * const p = m_pWeakConnectionPoint; | |||
242 | m_pWeakConnectionPoint = nullptr; | |||
243 | try { | |||
244 | p->dispose(); | |||
245 | } | |||
246 | catch (RuntimeException const& exc) { | |||
247 | SAL_WARN( "cppuhelper", exc )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "cppuhelper")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << exc) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << exc), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << exc; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "247" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << exc) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << exc), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << exc; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "247" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
248 | } | |||
249 | p->release(); | |||
250 | } | |||
251 | } | |||
252 | ||||
253 | OWeakObject::~OWeakObject() COVERITY_NOEXCEPT_FALSE | |||
254 | { | |||
255 | } | |||
256 | ||||
257 | // XWeak | |||
258 | Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter() | |||
259 | { | |||
260 | if (!m_pWeakConnectionPoint) | |||
261 | { | |||
262 | // only acquire mutex if member is not created | |||
263 | MutexGuard aGuard( getWeakMutex() ); | |||
264 | if( !m_pWeakConnectionPoint ) | |||
265 | { | |||
266 | OWeakConnectionPoint * p = new OWeakConnectionPoint(this); | |||
267 | p->acquire(); | |||
268 | m_pWeakConnectionPoint = p; | |||
269 | } | |||
270 | } | |||
271 | ||||
272 | return m_pWeakConnectionPoint; | |||
273 | } | |||
274 | ||||
275 | ||||
276 | //-- OWeakAggObject ---------------------------------------------------- | |||
277 | ||||
278 | OWeakAggObject::~OWeakAggObject() | |||
279 | { | |||
280 | } | |||
281 | ||||
282 | // XInterface | |||
283 | void OWeakAggObject::acquire() throw() | |||
284 | { | |||
285 | Reference<XInterface > x( xDelegator ); | |||
286 | if (x.is()) | |||
287 | x->acquire(); | |||
288 | else | |||
289 | OWeakObject::acquire(); | |||
290 | } | |||
291 | ||||
292 | // XInterface | |||
293 | void OWeakAggObject::release() throw() | |||
294 | { | |||
295 | Reference<XInterface > x( xDelegator ); | |||
296 | if (x.is()) | |||
297 | x->release(); | |||
298 | else | |||
299 | OWeakObject::release(); | |||
300 | } | |||
301 | ||||
302 | // XInterface | |||
303 | Any OWeakAggObject::queryInterface( const Type & rType ) | |||
304 | { | |||
305 | Reference< XInterface > x( xDelegator ); // harden ref | |||
306 | return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType )); | |||
307 | } | |||
308 | ||||
309 | // XAggregation | |||
310 | Any OWeakAggObject::queryAggregation( const Type & rType ) | |||
311 | { | |||
312 | return ::cppu::queryInterface( | |||
313 | rType, | |||
314 | static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ), | |||
315 | static_cast< XAggregation * >( this ), | |||
316 | static_cast< XWeak * >( this ) ); | |||
317 | } | |||
318 | ||||
319 | // XAggregation | |||
320 | void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) | |||
321 | { | |||
322 | xDelegator = rDelegator; | |||
323 | } | |||
324 | ||||
325 | } | |||
326 | ||||
327 | /** */ //for docpp | |||
328 | namespace com::sun::star::uno | |||
329 | { | |||
330 | ||||
331 | ||||
332 | //-- OWeakRefListener ----------------------------------------------------- | |||
333 | ||||
334 | class OWeakRefListener final : public XReference | |||
335 | { | |||
336 | public: | |||
337 | explicit OWeakRefListener(const Reference< XInterface >& xInt); | |||
338 | virtual ~OWeakRefListener(); | |||
339 | ||||
340 | // noncopyable | |||
341 | OWeakRefListener(const OWeakRefListener&) = delete; | |||
342 | const OWeakRefListener& operator=(const OWeakRefListener&) = delete; | |||
343 | ||||
344 | // XInterface | |||
345 | Any SAL_CALL queryInterface( const Type & rType ) override; | |||
346 | void SAL_CALL acquire() throw() override; | |||
347 | void SAL_CALL release() throw() override; | |||
348 | ||||
349 | // XReference | |||
350 | void SAL_CALL dispose() override; | |||
351 | ||||
352 | /// The reference counter. | |||
353 | oslInterlockedCount m_aRefCount; | |||
354 | /// The connection point of the weak object, guarded by getWeakMutex() | |||
355 | Reference< XAdapter > m_XWeakConnectionPoint; | |||
356 | }; | |||
357 | ||||
358 | OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) | |||
359 | : m_aRefCount( 1 ) | |||
360 | { | |||
361 | try | |||
362 | { | |||
363 | Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) ); | |||
364 | ||||
365 | if (xWeak.is()) | |||
366 | { | |||
367 | m_XWeakConnectionPoint = xWeak->queryAdapter(); | |||
368 | ||||
369 | if (m_XWeakConnectionPoint.is()) | |||
370 | { | |||
371 | m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this)); | |||
372 | } | |||
373 | } | |||
374 | } | |||
375 | catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "375" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); } // assert here, but no unexpected() | |||
376 | osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1); | |||
377 | } | |||
378 | ||||
379 | OWeakRefListener::~OWeakRefListener() | |||
380 | { | |||
381 | try | |||
382 | { | |||
383 | if (m_XWeakConnectionPoint.is()) | |||
384 | { | |||
385 | acquire(); // don't die again | |||
386 | m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this)); | |||
387 | } | |||
388 | } | |||
389 | catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "389" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); } // assert here, but no unexpected() | |||
390 | } | |||
391 | ||||
392 | // XInterface | |||
393 | Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) | |||
394 | { | |||
395 | return ::cppu::queryInterface( | |||
396 | rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) ); | |||
397 | } | |||
398 | ||||
399 | // XInterface | |||
400 | void SAL_CALL OWeakRefListener::acquire() throw() | |||
401 | { | |||
402 | osl_atomic_increment( &m_aRefCount )__sync_add_and_fetch((&m_aRefCount), 1); | |||
403 | } | |||
404 | ||||
405 | // XInterface | |||
406 | void SAL_CALL OWeakRefListener::release() throw() | |||
407 | { | |||
408 | if( ! osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1) ) | |||
409 | delete this; | |||
410 | } | |||
411 | ||||
412 | void SAL_CALL OWeakRefListener::dispose() | |||
413 | { | |||
414 | Reference< XAdapter > xAdp; | |||
415 | { | |||
416 | MutexGuard guard(cppu::getWeakMutex()); | |||
417 | if( m_XWeakConnectionPoint.is() ) | |||
418 | { | |||
419 | xAdp = m_XWeakConnectionPoint; | |||
420 | m_XWeakConnectionPoint.clear(); | |||
421 | } | |||
422 | } | |||
423 | ||||
424 | if( xAdp.is() ) | |||
425 | xAdp->removeReference(static_cast<XReference*>(this)); | |||
426 | } | |||
427 | ||||
428 | ||||
429 | //-- WeakReferenceHelper ---------------------------------------------------------- | |||
430 | ||||
431 | WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) | |||
432 | : m_pImpl( nullptr ) | |||
433 | { | |||
434 | if (xInt.is()) | |||
435 | { | |||
436 | m_pImpl = new OWeakRefListener(xInt); | |||
437 | m_pImpl->acquire(); | |||
438 | } | |||
439 | } | |||
440 | ||||
441 | WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) | |||
442 | : m_pImpl( nullptr ) | |||
443 | { | |||
444 | Reference< XInterface > xInt( rWeakRef.get() ); | |||
445 | if (xInt.is()) | |||
446 | { | |||
447 | m_pImpl = new OWeakRefListener(xInt); | |||
448 | m_pImpl->acquire(); | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | void WeakReferenceHelper::clear() | |||
453 | { | |||
454 | try | |||
455 | { | |||
456 | if (m_pImpl) | |||
457 | { | |||
458 | m_pImpl->dispose(); | |||
459 | m_pImpl->release(); | |||
460 | m_pImpl = nullptr; | |||
461 | } | |||
462 | } | |||
463 | catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "463" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); } // assert here, but no unexpected() | |||
464 | } | |||
465 | ||||
466 | WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) | |||
467 | { | |||
468 | if (this == &rWeakRef) | |||
469 | { | |||
470 | return *this; | |||
471 | } | |||
472 | Reference< XInterface > xInt( rWeakRef.get() ); | |||
473 | return operator = ( xInt ); | |||
474 | } | |||
475 | ||||
476 | WeakReferenceHelper & WeakReferenceHelper::operator =( | |||
477 | WeakReferenceHelper && other) | |||
478 | { | |||
479 | clear(); | |||
480 | std::swap(m_pImpl, other.m_pImpl); | |||
481 | return *this; | |||
482 | } | |||
483 | ||||
484 | WeakReferenceHelper & SAL_CALL | |||
485 | WeakReferenceHelper::operator= (const Reference< XInterface > & xInt) | |||
486 | { | |||
487 | try | |||
488 | { | |||
489 | clear(); | |||
490 | if (xInt.is()) | |||
491 | { | |||
492 | m_pImpl = new OWeakRefListener(xInt); | |||
493 | m_pImpl->acquire(); | |||
494 | } | |||
495 | } | |||
496 | catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "496" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); } // assert here, but no unexpected() | |||
497 | return *this; | |||
498 | } | |||
499 | ||||
500 | WeakReferenceHelper::~WeakReferenceHelper() | |||
501 | { | |||
502 | clear(); | |||
| ||||
503 | } | |||
504 | ||||
505 | Reference< XInterface > WeakReferenceHelper::get() const | |||
506 | { | |||
507 | try | |||
508 | { | |||
509 | Reference< XAdapter > xAdp; | |||
510 | { | |||
511 | // must lock to access m_XWeakConnectionPoint | |||
512 | MutexGuard guard(cppu::getWeakMutex()); | |||
513 | if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() ) | |||
514 | xAdp = m_pImpl->m_XWeakConnectionPoint; | |||
515 | } | |||
516 | ||||
517 | if (xAdp.is()) | |||
518 | return xAdp->queryAdapted(); | |||
519 | } | |||
520 | catch (RuntimeException &) | |||
521 | { | |||
522 | OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx" ":" "522" ": "), "OSL_ASSERT: %s", "false"); } } while (false ); | |||
523 | } // assert here, but no unexpected() | |||
524 | ||||
525 | return Reference< XInterface >(); | |||
526 | } | |||
527 | ||||
528 | } | |||
529 | ||||
530 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX | ||||
20 | #define INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX | ||||
21 | |||||
22 | #include "sal/config.h" | ||||
23 | |||||
24 | #include <cstddef> | ||||
25 | #include <ostream> | ||||
26 | |||||
27 | #include "com/sun/star/uno/Reference.h" | ||||
28 | #include "com/sun/star/uno/RuntimeException.hpp" | ||||
29 | #include "com/sun/star/uno/XInterface.hpp" | ||||
30 | #include "com/sun/star/uno/Any.hxx" | ||||
31 | #include "cppu/cppudllapi.h" | ||||
32 | |||||
33 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) rtl_uString * SAL_CALL cppu_unsatisfied_iquery_msg( | ||||
34 | typelib_TypeDescriptionReference * pType ) | ||||
35 | SAL_THROW_EXTERN_C()throw (); | ||||
36 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) rtl_uString * SAL_CALL cppu_unsatisfied_iset_msg( | ||||
37 | typelib_TypeDescriptionReference * pType ) | ||||
38 | SAL_THROW_EXTERN_C()throw (); | ||||
39 | |||||
40 | namespace com | ||||
41 | { | ||||
42 | namespace sun | ||||
43 | { | ||||
44 | namespace star | ||||
45 | { | ||||
46 | namespace uno | ||||
47 | { | ||||
48 | |||||
49 | |||||
50 | inline XInterface * BaseReference::iquery( | ||||
51 | XInterface * pInterface, const Type & rType ) | ||||
52 | { | ||||
53 | if (pInterface) | ||||
54 | { | ||||
55 | Any aRet( pInterface->queryInterface( rType ) ); | ||||
56 | if (typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass) | ||||
57 | { | ||||
58 | XInterface * pRet = static_cast< XInterface * >( aRet.pReserved ); | ||||
59 | aRet.pReserved = NULL__null; | ||||
60 | return pRet; | ||||
61 | } | ||||
62 | } | ||||
63 | return NULL__null; | ||||
64 | } | ||||
65 | |||||
66 | template< class interface_type > | ||||
67 | inline XInterface * Reference< interface_type >::iquery( | ||||
68 | XInterface * pInterface ) | ||||
69 | { | ||||
70 | return BaseReference::iquery(pInterface, interface_type::static_type()); | ||||
71 | } | ||||
72 | |||||
73 | inline XInterface * BaseReference::iquery_throw( | ||||
74 | XInterface * pInterface, const Type & rType ) | ||||
75 | { | ||||
76 | XInterface * pQueried = iquery( pInterface, rType ); | ||||
77 | if (pQueried) | ||||
78 | return pQueried; | ||||
79 | throw RuntimeException( | ||||
80 | ::rtl::OUString( cppu_unsatisfied_iquery_msg( rType.getTypeLibType() ), SAL_NO_ACQUIRE ), | ||||
81 | Reference< XInterface >( pInterface ) ); | ||||
82 | } | ||||
83 | |||||
84 | template< class interface_type > | ||||
85 | inline XInterface * Reference< interface_type >::iquery_throw( | ||||
86 | XInterface * pInterface ) | ||||
87 | { | ||||
88 | return BaseReference::iquery_throw( | ||||
89 | pInterface, interface_type::static_type()); | ||||
90 | } | ||||
91 | |||||
92 | template< class interface_type > | ||||
93 | inline interface_type * Reference< interface_type >::iset_throw( | ||||
94 | interface_type * pInterface ) | ||||
95 | { | ||||
96 | if (pInterface) | ||||
97 | { | ||||
98 | castToXInterface(pInterface)->acquire(); | ||||
99 | return pInterface; | ||||
100 | } | ||||
101 | throw RuntimeException( | ||||
102 | ::rtl::OUString( cppu_unsatisfied_iset_msg( interface_type::static_type().getTypeLibType() ), SAL_NO_ACQUIRE ), | ||||
103 | NULL__null ); | ||||
104 | } | ||||
105 | |||||
106 | template< class interface_type > | ||||
107 | inline Reference< interface_type >::~Reference() COVERITY_NOEXCEPT_FALSE | ||||
108 | { | ||||
109 | if (_pInterface
| ||||
| |||||
110 | _pInterface->release(); | ||||
111 | } | ||||
112 | |||||
113 | template< class interface_type > | ||||
114 | inline Reference< interface_type >::Reference() | ||||
115 | { | ||||
116 | _pInterface = NULL__null; | ||||
117 | } | ||||
118 | |||||
119 | template< class interface_type > | ||||
120 | inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef ) | ||||
121 | { | ||||
122 | _pInterface = rRef._pInterface; | ||||
123 | if (_pInterface) | ||||
124 | _pInterface->acquire(); | ||||
125 | } | ||||
126 | |||||
127 | #if defined LIBO_INTERNAL_ONLY1 | ||||
128 | template< class interface_type > | ||||
129 | inline Reference< interface_type >::Reference( Reference< interface_type > && rRef ) noexcept | ||||
130 | { | ||||
131 | _pInterface = rRef._pInterface; | ||||
132 | rRef._pInterface = nullptr; | ||||
133 | } | ||||
134 | |||||
135 | template< class interface_type > template< class derived_type > | ||||
136 | inline Reference< interface_type >::Reference( | ||||
137 | const Reference< derived_type > & rRef, | ||||
138 | std::enable_if_t< | ||||
139 | std::is_base_of_v<interface_type, derived_type> | ||||
140 | && !std::is_same_v<interface_type, XInterface>, void *>) | ||||
141 | { | ||||
142 | interface_type * p = rRef.get(); | ||||
143 | _pInterface = p; | ||||
144 | if (_pInterface) | ||||
145 | _pInterface->acquire(); | ||||
146 | } | ||||
147 | #endif | ||||
148 | |||||
149 | template< class interface_type > | ||||
150 | inline Reference< interface_type >::Reference( interface_type * pInterface ) | ||||
151 | { | ||||
152 | _pInterface = castToXInterface(pInterface); | ||||
153 | if (_pInterface) | ||||
154 | _pInterface->acquire(); | ||||
155 | } | ||||
156 | |||||
157 | template< class interface_type > | ||||
158 | inline Reference< interface_type >::Reference( interface_type * pInterface, __sal_NoAcquire ) | ||||
159 | { | ||||
160 | _pInterface = castToXInterface(pInterface); | ||||
161 | } | ||||
162 | |||||
163 | template< class interface_type > | ||||
164 | inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_NoAcquire ) | ||||
165 | { | ||||
166 | _pInterface = castToXInterface(pInterface); | ||||
167 | } | ||||
168 | |||||
169 | template< class interface_type > | ||||
170 | inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_Query ) | ||||
171 | { | ||||
172 | _pInterface = iquery( rRef.get() ); | ||||
173 | } | ||||
174 | |||||
175 | template< class interface_type > | ||||
176 | inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_Query ) | ||||
177 | { | ||||
178 | _pInterface = iquery( pInterface ); | ||||
179 | } | ||||
180 | |||||
181 | template< class interface_type > | ||||
182 | inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_Query ) | ||||
183 | { | ||||
184 | _pInterface = (typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass | ||||
185 | ? iquery( static_cast< XInterface * >( rAny.pReserved ) ) : NULL__null); | ||||
186 | } | ||||
187 | |||||
188 | template< class interface_type > | ||||
189 | inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_QueryThrow ) | ||||
190 | { | ||||
191 | _pInterface = iquery_throw( rRef.get() ); | ||||
192 | } | ||||
193 | |||||
194 | template< class interface_type > | ||||
195 | inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_QueryThrow ) | ||||
196 | { | ||||
197 | _pInterface = iquery_throw( pInterface ); | ||||
198 | } | ||||
199 | |||||
200 | template< class interface_type > | ||||
201 | inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_QueryThrow ) | ||||
202 | { | ||||
203 | _pInterface = iquery_throw( typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass | ||||
204 | ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null ); | ||||
205 | } | ||||
206 | |||||
207 | template< class interface_type > | ||||
208 | inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef, UnoReference_SetThrow ) | ||||
209 | { | ||||
210 | _pInterface = castToXInterface( iset_throw( rRef.get() ) ); | ||||
211 | } | ||||
212 | |||||
213 | template< class interface_type > | ||||
214 | inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_SetThrow ) | ||||
215 | { | ||||
216 | _pInterface = castToXInterface( iset_throw( pInterface ) ); | ||||
217 | } | ||||
218 | |||||
219 | |||||
220 | template< class interface_type > | ||||
221 | inline void Reference< interface_type >::clear() | ||||
222 | { | ||||
223 | if (_pInterface) | ||||
224 | { | ||||
225 | XInterface * const pOld = _pInterface; | ||||
226 | _pInterface = NULL__null; | ||||
227 | pOld->release(); | ||||
228 | } | ||||
229 | } | ||||
230 | |||||
231 | template< class interface_type > | ||||
232 | inline bool Reference< interface_type >::set( | ||||
233 | interface_type * pInterface ) | ||||
234 | { | ||||
235 | if (pInterface) | ||||
236 | castToXInterface(pInterface)->acquire(); | ||||
237 | XInterface * const pOld = _pInterface; | ||||
238 | _pInterface = castToXInterface(pInterface); | ||||
239 | if (pOld) | ||||
240 | pOld->release(); | ||||
241 | return (NULL__null != pInterface); | ||||
242 | } | ||||
243 | |||||
244 | template< class interface_type > | ||||
245 | inline bool Reference< interface_type >::set( | ||||
246 | interface_type * pInterface, __sal_NoAcquire ) | ||||
247 | { | ||||
248 | XInterface * const pOld = _pInterface; | ||||
249 | _pInterface = castToXInterface(pInterface); | ||||
250 | if (pOld) | ||||
251 | pOld->release(); | ||||
252 | return (NULL__null != pInterface); | ||||
253 | } | ||||
254 | |||||
255 | template< class interface_type > | ||||
256 | inline bool Reference< interface_type >::set( | ||||
257 | interface_type * pInterface, UnoReference_NoAcquire ) | ||||
258 | { | ||||
259 | return set( pInterface, SAL_NO_ACQUIRE ); | ||||
260 | } | ||||
261 | |||||
262 | |||||
263 | template< class interface_type > | ||||
264 | inline bool Reference< interface_type >::set( | ||||
265 | const Reference< interface_type > & rRef ) | ||||
266 | { | ||||
267 | return set( castFromXInterface( rRef._pInterface ) ); | ||||
268 | } | ||||
269 | |||||
270 | template< class interface_type > | ||||
271 | inline bool Reference< interface_type >::set( | ||||
272 | XInterface * pInterface, UnoReference_Query ) | ||||
273 | { | ||||
274 | return set( castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE ); | ||||
275 | } | ||||
276 | |||||
277 | template< class interface_type > | ||||
278 | inline bool Reference< interface_type >::set( | ||||
279 | const BaseReference & rRef, UnoReference_Query ) | ||||
280 | { | ||||
281 | return set( castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE ); | ||||
282 | } | ||||
283 | |||||
284 | |||||
285 | template< class interface_type > | ||||
286 | inline bool Reference< interface_type >::set( | ||||
287 | Any const & rAny, UnoReference_Query ) | ||||
288 | { | ||||
289 | return set( | ||||
290 | castFromXInterface( | ||||
291 | iquery( | ||||
292 | rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE | ||||
293 | ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null )), | ||||
294 | SAL_NO_ACQUIRE ); | ||||
295 | } | ||||
296 | |||||
297 | |||||
298 | template< class interface_type > | ||||
299 | inline void Reference< interface_type >::set( | ||||
300 | XInterface * pInterface, UnoReference_QueryThrow ) | ||||
301 | { | ||||
302 | set( castFromXInterface(iquery_throw( pInterface )), SAL_NO_ACQUIRE ); | ||||
303 | } | ||||
304 | |||||
305 | template< class interface_type > | ||||
306 | inline void Reference< interface_type >::set( | ||||
307 | const BaseReference & rRef, UnoReference_QueryThrow ) | ||||
308 | { | ||||
309 | set( castFromXInterface(iquery_throw( rRef.get() )), SAL_NO_ACQUIRE ); | ||||
310 | } | ||||
311 | |||||
312 | |||||
313 | template< class interface_type > | ||||
314 | inline void Reference< interface_type >::set( | ||||
315 | Any const & rAny, UnoReference_QueryThrow ) | ||||
316 | { | ||||
317 | set( castFromXInterface( | ||||
318 | iquery_throw( | ||||
319 | rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE | ||||
320 | ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null )), | ||||
321 | SAL_NO_ACQUIRE ); | ||||
322 | } | ||||
323 | |||||
324 | template< class interface_type > | ||||
325 | inline void Reference< interface_type >::set( | ||||
326 | interface_type * pInterface, UnoReference_SetThrow ) | ||||
327 | { | ||||
328 | set( iset_throw( pInterface ), SAL_NO_ACQUIRE ); | ||||
329 | } | ||||
330 | |||||
331 | template< class interface_type > | ||||
332 | inline void Reference< interface_type >::set( | ||||
333 | const Reference< interface_type > & rRef, UnoReference_SetThrow ) | ||||
334 | { | ||||
335 | set( rRef.get(), UNO_SET_THROW ); | ||||
336 | } | ||||
337 | |||||
338 | |||||
339 | template< class interface_type > | ||||
340 | inline Reference< interface_type > & Reference< interface_type >::operator = ( | ||||
341 | interface_type * pInterface ) | ||||
342 | { | ||||
343 | set( pInterface ); | ||||
344 | return *this; | ||||
345 | } | ||||
346 | |||||
347 | template< class interface_type > | ||||
348 | inline Reference< interface_type > & Reference< interface_type >::operator = ( | ||||
349 | const Reference< interface_type > & rRef ) | ||||
350 | { | ||||
351 | set( castFromXInterface( rRef._pInterface ) ); | ||||
352 | return *this; | ||||
353 | } | ||||
354 | |||||
355 | #if defined LIBO_INTERNAL_ONLY1 | ||||
356 | template< class interface_type > | ||||
357 | inline Reference< interface_type > & Reference< interface_type >::operator = ( | ||||
358 | Reference< interface_type > && rRef ) noexcept | ||||
359 | { | ||||
360 | if (_pInterface) | ||||
361 | _pInterface->release(); | ||||
362 | _pInterface = rRef._pInterface; | ||||
363 | rRef._pInterface = nullptr; | ||||
364 | return *this; | ||||
365 | } | ||||
366 | #endif | ||||
367 | |||||
368 | template< class interface_type > | ||||
369 | inline Reference< interface_type > Reference< interface_type >::query( | ||||
370 | const BaseReference & rRef ) | ||||
371 | { | ||||
372 | return Reference< interface_type >( | ||||
373 | castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE ); | ||||
374 | } | ||||
375 | |||||
376 | template< class interface_type > | ||||
377 | inline Reference< interface_type > Reference< interface_type >::query( | ||||
378 | XInterface * pInterface ) | ||||
379 | { | ||||
380 | return Reference< interface_type >( | ||||
381 | castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE ); | ||||
382 | } | ||||
383 | |||||
384 | |||||
385 | inline bool BaseReference::operator == ( XInterface * pInterface ) const | ||||
386 | { | ||||
387 | if (_pInterface == pInterface) | ||||
388 | return true; | ||||
389 | try | ||||
390 | { | ||||
391 | // only the query to XInterface must return the same pointer if they belong to same objects | ||||
392 | Reference< XInterface > x1( _pInterface, UNO_QUERY ); | ||||
393 | Reference< XInterface > x2( pInterface, UNO_QUERY ); | ||||
394 | return (x1._pInterface == x2._pInterface); | ||||
395 | } | ||||
396 | catch (RuntimeException &) | ||||
397 | { | ||||
398 | return false; | ||||
399 | } | ||||
400 | } | ||||
401 | |||||
402 | |||||
403 | inline bool BaseReference::operator < ( | ||||
404 | const BaseReference & rRef ) const | ||||
405 | { | ||||
406 | if (_pInterface == rRef._pInterface) | ||||
407 | return false; | ||||
408 | try | ||||
409 | { | ||||
410 | // only the query to XInterface must return the same pointer: | ||||
411 | Reference< XInterface > x1( _pInterface, UNO_QUERY ); | ||||
412 | Reference< XInterface > x2( rRef, UNO_QUERY ); | ||||
413 | return (x1._pInterface < x2._pInterface); | ||||
414 | } | ||||
415 | catch (RuntimeException &) | ||||
416 | { | ||||
417 | return false; | ||||
418 | } | ||||
419 | } | ||||
420 | |||||
421 | |||||
422 | inline bool BaseReference::operator != ( XInterface * pInterface ) const | ||||
423 | { | ||||
424 | return (! operator == ( pInterface )); | ||||
425 | } | ||||
426 | |||||
427 | inline bool BaseReference::operator == ( const BaseReference & rRef ) const | ||||
428 | { | ||||
429 | return operator == ( rRef._pInterface ); | ||||
430 | } | ||||
431 | |||||
432 | inline bool BaseReference::operator != ( const BaseReference & rRef ) const | ||||
433 | { | ||||
434 | return (! operator == ( rRef._pInterface )); | ||||
435 | } | ||||
436 | |||||
437 | #if defined LIBO_INTERNAL_ONLY1 | ||||
438 | /** | ||||
439 | Support for BaseReference in std::ostream (and thus in CPPUNIT_ASSERT or | ||||
440 | SAL_INFO macros, for example). | ||||
441 | |||||
442 | @since LibreOffice 5.4 | ||||
443 | */ | ||||
444 | template<typename charT, typename traits> std::basic_ostream<charT, traits> & | ||||
445 | operator <<( | ||||
446 | std::basic_ostream<charT, traits> & stream, BaseReference const & ref) | ||||
447 | { return stream << ref.get(); } | ||||
448 | #endif | ||||
449 | |||||
450 | } | ||||
451 | } | ||||
452 | } | ||||
453 | } | ||||
454 | |||||
455 | #if defined LIBO_INTERNAL_ONLY1 | ||||
456 | namespace std | ||||
457 | { | ||||
458 | |||||
459 | /** | ||||
460 | Make css::uno::Reference hashable by default for use in STL containers. | ||||
461 | |||||
462 | @since LibreOffice 6.3 | ||||
463 | */ | ||||
464 | template<typename T> | ||||
465 | struct hash<::css::uno::Reference<T>> | ||||
466 | { | ||||
467 | std::size_t operator()(::css::uno::Reference<T> const & s) const | ||||
468 | { return size_t(s.get()); } | ||||
469 | }; | ||||
470 | |||||
471 | } | ||||
472 | |||||
473 | #endif | ||||
474 | |||||
475 | #endif | ||||
476 | |||||
477 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |