...(for now, from LIBO_INTERNAL_CODE only). See the mail thread starting at <https://lists.freedesktop.org/archives/libreoffice/2017-January/076665.html> "Dynamic Exception Specifications" for details. Most changes have been done automatically by the rewriting loplugin:dynexcspec (after enabling the rewriting mode, to be committed shortly). The way it only removes exception specs from declarations if it also sees a definition, it identified some dead declarations-w/o-definitions (that have been removed manually) and some cases where a definition appeared in multiple include files (which have also been cleaned up manually). There's also been cases of macro paramters (that were used to abstract over exception specs) that have become unused now (and been removed). Furthermore, some code needed to be cleaned up manually (avmedia/source/quicktime/ and connectivity/source/drivers/kab/), as I had no configurations available that would actually build that code. Missing @throws documentation has not been applied in such manual clean-up. Change-Id: I3408691256c9b0c12bc5332de976743626e13960 Reviewed-on: https://gerrit.libreoffice.org/33574 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
545 lines
14 KiB
C++
545 lines
14 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <osl/mutex.hxx>
|
|
#include <cppuhelper/weakagg.hxx>
|
|
#include <cppuhelper/interfacecontainer.hxx>
|
|
#include <cppuhelper/exc_hlp.hxx>
|
|
#include <cppuhelper/queryinterface.hxx>
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
using namespace osl;
|
|
using namespace com::sun::star::uno;
|
|
|
|
/** */ //for docpp
|
|
namespace cppu
|
|
{
|
|
|
|
// due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
|
|
// this is used to lock all instances of OWeakConnectionPoint and OWeakRefListener as well as OWeakObject::m_pWeakConnectionPoint
|
|
inline static Mutex & getWeakMutex()
|
|
{
|
|
static Mutex * s_pMutex = nullptr;
|
|
if (! s_pMutex)
|
|
s_pMutex = new Mutex();
|
|
return *s_pMutex;
|
|
}
|
|
|
|
|
|
//-- OWeakConnectionPoint ----------------------------------------------------
|
|
|
|
class OWeakConnectionPoint: public XAdapter
|
|
{
|
|
public:
|
|
/**
|
|
Hold the weak object without an acquire (only the pointer).
|
|
*/
|
|
explicit OWeakConnectionPoint( OWeakObject* pObj )
|
|
: m_aRefCount( 0 )
|
|
, m_pObject(pObj)
|
|
{}
|
|
|
|
// noncopyable
|
|
OWeakConnectionPoint(const OWeakConnectionPoint&) = delete;
|
|
const OWeakConnectionPoint& operator=(const OWeakConnectionPoint&) = delete;
|
|
|
|
// XInterface
|
|
Any SAL_CALL queryInterface( const Type & rType ) override;
|
|
void SAL_CALL acquire() throw() override;
|
|
void SAL_CALL release() throw() override;
|
|
|
|
// XAdapter
|
|
css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override;
|
|
void SAL_CALL addReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
|
|
void SAL_CALL removeReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
|
|
|
|
/// Called from the weak object if the reference count goes to zero.
|
|
///
|
|
/// @throws css::uno::RuntimeException
|
|
void SAL_CALL dispose();
|
|
|
|
private:
|
|
virtual ~OWeakConnectionPoint() {}
|
|
|
|
/// The reference counter.
|
|
oslInterlockedCount m_aRefCount;
|
|
/// The weak object
|
|
OWeakObject* m_pObject;
|
|
/// The container to hold the weak references
|
|
std::vector<Reference<XReference>> m_aReferences;
|
|
};
|
|
|
|
// XInterface
|
|
Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
|
|
{
|
|
return ::cppu::queryInterface(
|
|
rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakConnectionPoint::acquire() throw()
|
|
{
|
|
osl_atomic_increment( &m_aRefCount );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakConnectionPoint::release() throw()
|
|
{
|
|
if (! osl_atomic_decrement( &m_aRefCount ))
|
|
delete this;
|
|
}
|
|
|
|
void SAL_CALL OWeakConnectionPoint::dispose()
|
|
{
|
|
std::vector<Reference<XReference>> aCopy;
|
|
{ // only hold the mutex while we access the field
|
|
MutexGuard aGuard(getWeakMutex());
|
|
// OWeakObject is not the only owner of this, so clear m_pObject
|
|
// so that queryAdapted() won't use it now that it's dead
|
|
m_pObject = nullptr;
|
|
// other code is going to call removeReference while we are doing this, so we need a
|
|
// copy, but since we are disposing and going away, we can just take the original data
|
|
aCopy.swap(m_aReferences);
|
|
}
|
|
Any ex;
|
|
for (const Reference<XReference> & i : aCopy )
|
|
{
|
|
try
|
|
{
|
|
i->dispose();
|
|
}
|
|
catch (css::lang::DisposedException &) {}
|
|
catch (RuntimeException &)
|
|
{
|
|
ex = cppu::getCaughtException();
|
|
}
|
|
}
|
|
if (ex.hasValue())
|
|
{
|
|
cppu::throwException(ex);
|
|
}
|
|
}
|
|
|
|
// XInterface
|
|
Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted()
|
|
{
|
|
Reference< XInterface > ret;
|
|
|
|
ClearableMutexGuard guard(getWeakMutex());
|
|
|
|
if (m_pObject)
|
|
{
|
|
oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
|
|
|
|
if (n > 1)
|
|
{
|
|
// The reference is incremented. The object cannot be destroyed.
|
|
// Release the guard at the earliest point.
|
|
guard.clear();
|
|
// WeakObject has a (XInterface *) cast operator
|
|
ret = *m_pObject;
|
|
osl_atomic_decrement( &m_pObject->m_refCount );
|
|
}
|
|
else
|
|
// Another thread wait in the dispose method at the guard
|
|
osl_atomic_decrement( &m_pObject->m_refCount );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
|
|
{
|
|
MutexGuard aGuard(getWeakMutex());
|
|
m_aReferences.push_back( rRef );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
|
|
{
|
|
MutexGuard aGuard(getWeakMutex());
|
|
// Search from end because the thing that last added a ref is most likely to be the
|
|
// first to remove a ref.
|
|
// It's not really valid to compare the pointer directly, but it's faster.
|
|
for (auto it = m_aReferences.rbegin(); it != m_aReferences.rend(); ++it) {
|
|
if (it->get() == rRef.get()) {
|
|
m_aReferences.erase( it.base()-1 );
|
|
return;
|
|
}
|
|
}
|
|
// interface not found, use the correct compare method
|
|
auto it = std::find(m_aReferences.rbegin(), m_aReferences.rend(), rRef);
|
|
if ( it != m_aReferences.rend() )
|
|
m_aReferences.erase( it.base()-1 );
|
|
}
|
|
|
|
|
|
//-- OWeakObject -------------------------------------------------------
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
// Accidentally occurs in msvc mapfile = > had to be outlined.
|
|
OWeakObject::OWeakObject()
|
|
: m_refCount( 0 ),
|
|
m_pWeakConnectionPoint( nullptr )
|
|
{
|
|
}
|
|
#endif
|
|
|
|
// XInterface
|
|
Any SAL_CALL OWeakObject::queryInterface( const Type & rType )
|
|
{
|
|
return ::cppu::queryInterface(
|
|
rType,
|
|
static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakObject::acquire() throw()
|
|
{
|
|
osl_atomic_increment( &m_refCount );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakObject::release() throw()
|
|
{
|
|
if (osl_atomic_decrement( &m_refCount ) == 0) {
|
|
// notify/clear all weak-refs before object's dtor is executed
|
|
// (which may check weak-refs to this object):
|
|
disposeWeakConnectionPoint();
|
|
// destroy object:
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
void OWeakObject::disposeWeakConnectionPoint()
|
|
{
|
|
OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
|
|
if (m_pWeakConnectionPoint != nullptr) {
|
|
OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
|
|
m_pWeakConnectionPoint = nullptr;
|
|
try {
|
|
p->dispose();
|
|
}
|
|
catch (RuntimeException const& exc) {
|
|
OSL_FAIL(
|
|
OUStringToOString(
|
|
exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
|
|
static_cast<void>(exc);
|
|
}
|
|
p->release();
|
|
}
|
|
}
|
|
|
|
OWeakObject::~OWeakObject()
|
|
{
|
|
}
|
|
|
|
// XWeak
|
|
Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
|
|
{
|
|
if (!m_pWeakConnectionPoint)
|
|
{
|
|
// only acquire mutex if member is not created
|
|
MutexGuard aGuard( getWeakMutex() );
|
|
if( !m_pWeakConnectionPoint )
|
|
{
|
|
OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
|
|
p->acquire();
|
|
m_pWeakConnectionPoint = p;
|
|
}
|
|
}
|
|
|
|
return m_pWeakConnectionPoint;
|
|
}
|
|
|
|
|
|
//-- OWeakAggObject ----------------------------------------------------
|
|
|
|
OWeakAggObject::~OWeakAggObject()
|
|
{
|
|
}
|
|
|
|
// XInterface
|
|
void OWeakAggObject::acquire() throw()
|
|
{
|
|
Reference<XInterface > x( xDelegator );
|
|
if (x.is())
|
|
x->acquire();
|
|
else
|
|
OWeakObject::acquire();
|
|
}
|
|
|
|
// XInterface
|
|
void OWeakAggObject::release() throw()
|
|
{
|
|
Reference<XInterface > x( xDelegator );
|
|
if (x.is())
|
|
x->release();
|
|
else
|
|
OWeakObject::release();
|
|
}
|
|
|
|
// XInterface
|
|
Any OWeakAggObject::queryInterface( const Type & rType )
|
|
{
|
|
Reference< XInterface > x( xDelegator ); // harden ref
|
|
return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
|
|
}
|
|
|
|
// XAggregation
|
|
Any OWeakAggObject::queryAggregation( const Type & rType )
|
|
{
|
|
return ::cppu::queryInterface(
|
|
rType,
|
|
static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
|
|
static_cast< XAggregation * >( this ),
|
|
static_cast< XWeak * >( this ) );
|
|
}
|
|
|
|
// XAggregation
|
|
void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator )
|
|
{
|
|
xDelegator = rDelegator;
|
|
}
|
|
|
|
}
|
|
|
|
/** */ //for docpp
|
|
namespace com
|
|
{
|
|
/** */ //for docpp
|
|
namespace sun
|
|
{
|
|
/** */ //for docpp
|
|
namespace star
|
|
{
|
|
/** */ //for docpp
|
|
namespace uno
|
|
{
|
|
|
|
|
|
//-- OWeakRefListener -----------------------------------------------------
|
|
|
|
class OWeakRefListener: public XReference
|
|
{
|
|
public:
|
|
explicit OWeakRefListener(const Reference< XInterface >& xInt);
|
|
virtual ~OWeakRefListener();
|
|
|
|
// noncopyable
|
|
OWeakRefListener(const OWeakRefListener&) = delete;
|
|
const OWeakRefListener& operator=(const OWeakRefListener&) = delete;
|
|
|
|
// XInterface
|
|
Any SAL_CALL queryInterface( const Type & rType ) override;
|
|
void SAL_CALL acquire() throw() override;
|
|
void SAL_CALL release() throw() override;
|
|
|
|
// XReference
|
|
void SAL_CALL dispose() override;
|
|
|
|
/// The reference counter.
|
|
oslInterlockedCount m_aRefCount;
|
|
/// The connection point of the weak object, guarded by getWeakMutex()
|
|
Reference< XAdapter > m_XWeakConnectionPoint;
|
|
};
|
|
|
|
OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt)
|
|
: m_aRefCount( 1 )
|
|
{
|
|
try
|
|
{
|
|
Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
|
|
|
|
if (xWeak.is())
|
|
{
|
|
m_XWeakConnectionPoint = xWeak->queryAdapter();
|
|
|
|
if (m_XWeakConnectionPoint.is())
|
|
{
|
|
m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
|
|
}
|
|
}
|
|
}
|
|
catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
|
|
osl_atomic_decrement( &m_aRefCount );
|
|
}
|
|
|
|
OWeakRefListener::~OWeakRefListener()
|
|
{
|
|
try
|
|
{
|
|
if (m_XWeakConnectionPoint.is())
|
|
{
|
|
acquire(); // don't die again
|
|
m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
|
|
}
|
|
}
|
|
catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
|
|
}
|
|
|
|
// XInterface
|
|
Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType )
|
|
{
|
|
return ::cppu::queryInterface(
|
|
rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakRefListener::acquire() throw()
|
|
{
|
|
osl_atomic_increment( &m_aRefCount );
|
|
}
|
|
|
|
// XInterface
|
|
void SAL_CALL OWeakRefListener::release() throw()
|
|
{
|
|
if( ! osl_atomic_decrement( &m_aRefCount ) )
|
|
delete this;
|
|
}
|
|
|
|
void SAL_CALL OWeakRefListener::dispose()
|
|
{
|
|
Reference< XAdapter > xAdp;
|
|
{
|
|
MutexGuard guard(cppu::getWeakMutex());
|
|
if( m_XWeakConnectionPoint.is() )
|
|
{
|
|
xAdp = m_XWeakConnectionPoint;
|
|
m_XWeakConnectionPoint.clear();
|
|
}
|
|
}
|
|
|
|
if( xAdp.is() )
|
|
xAdp->removeReference(static_cast<XReference*>(this));
|
|
}
|
|
|
|
|
|
//-- WeakReferenceHelper ----------------------------------------------------------
|
|
|
|
WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt)
|
|
: m_pImpl( nullptr )
|
|
{
|
|
if (xInt.is())
|
|
{
|
|
m_pImpl = new OWeakRefListener(xInt);
|
|
m_pImpl->acquire();
|
|
}
|
|
}
|
|
|
|
WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef)
|
|
: m_pImpl( nullptr )
|
|
{
|
|
Reference< XInterface > xInt( rWeakRef.get() );
|
|
if (xInt.is())
|
|
{
|
|
m_pImpl = new OWeakRefListener(xInt);
|
|
m_pImpl->acquire();
|
|
}
|
|
}
|
|
|
|
void WeakReferenceHelper::clear()
|
|
{
|
|
try
|
|
{
|
|
if (m_pImpl)
|
|
{
|
|
m_pImpl->dispose();
|
|
m_pImpl->release();
|
|
m_pImpl = nullptr;
|
|
}
|
|
}
|
|
catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
|
|
}
|
|
|
|
WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef)
|
|
{
|
|
if (this == &rWeakRef)
|
|
{
|
|
return *this;
|
|
}
|
|
Reference< XInterface > xInt( rWeakRef.get() );
|
|
return operator = ( xInt );
|
|
}
|
|
|
|
WeakReferenceHelper & WeakReferenceHelper::operator =(
|
|
WeakReferenceHelper && other)
|
|
{
|
|
clear();
|
|
std::swap(m_pImpl, other.m_pImpl);
|
|
return *this;
|
|
}
|
|
|
|
WeakReferenceHelper & SAL_CALL
|
|
WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
|
|
{
|
|
try
|
|
{
|
|
clear();
|
|
if (xInt.is())
|
|
{
|
|
m_pImpl = new OWeakRefListener(xInt);
|
|
m_pImpl->acquire();
|
|
}
|
|
}
|
|
catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
|
|
return *this;
|
|
}
|
|
|
|
WeakReferenceHelper::~WeakReferenceHelper()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
Reference< XInterface > WeakReferenceHelper::get() const
|
|
{
|
|
try
|
|
{
|
|
Reference< XAdapter > xAdp;
|
|
{
|
|
// must lock to access m_XWeakConnectionPoint
|
|
MutexGuard guard(cppu::getWeakMutex());
|
|
if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
|
|
xAdp = m_pImpl->m_XWeakConnectionPoint;
|
|
}
|
|
|
|
if (xAdp.is())
|
|
return xAdp->queryAdapted();
|
|
}
|
|
catch (RuntimeException &)
|
|
{
|
|
OSL_ASSERT( false );
|
|
} // assert here, but no unexpected()
|
|
|
|
return Reference< XInterface >();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|