summaryrefslogtreecommitdiff
path: root/cppuhelper/source
diff options
context:
space:
mode:
Diffstat (limited to 'cppuhelper/source')
-rw-r--r--cppuhelper/source/compbase.cxx231
-rw-r--r--cppuhelper/source/component_context.cxx49
-rw-r--r--cppuhelper/source/unoimplbase.cxx27
3 files changed, 284 insertions, 23 deletions
diff --git a/cppuhelper/source/compbase.cxx b/cppuhelper/source/compbase.cxx
new file mode 100644
index 000000000000..ed4909b71106
--- /dev/null
+++ b/cppuhelper/source/compbase.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#include <compbase2.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+
+namespace cppuhelper
+{
+WeakComponentImplHelperBase2::~WeakComponentImplHelperBase2() {}
+
+// css::lang::XComponent
+void SAL_CALL WeakComponentImplHelperBase2::dispose()
+{
+ std::unique_lock aGuard(m_aMutex);
+ if (m_bDisposed)
+ return;
+ m_bDisposed = true;
+ disposing(aGuard);
+ if (!aGuard.owns_lock())
+ aGuard.lock();
+ css::lang::EventObject aEvt(static_cast<OWeakObject*>(this));
+ maEventListeners.disposeAndClear(aGuard, aEvt);
+}
+
+void WeakComponentImplHelperBase2::disposing(std::unique_lock<std::mutex>&) {}
+
+void SAL_CALL WeakComponentImplHelperBase2::addEventListener(
+ css::uno::Reference<css::lang::XEventListener> const& rxListener)
+{
+ std::unique_lock aGuard(m_aMutex);
+ if (m_bDisposed)
+ return;
+ maEventListeners.addInterface(aGuard, rxListener);
+}
+
+void SAL_CALL WeakComponentImplHelperBase2::removeEventListener(
+ css::uno::Reference<css::lang::XEventListener> const& rxListener)
+{
+ std::unique_lock aGuard(m_aMutex);
+ maEventListeners.removeInterface(aGuard, rxListener);
+}
+
+css::uno::Any SAL_CALL WeakComponentImplHelperBase2::queryInterface(css::uno::Type const& rType)
+{
+ css::uno::Any aReturn = ::cppu::queryInterface(rType, static_cast<css::uno::XWeak*>(this),
+ static_cast<css::lang::XComponent*>(this));
+ if (aReturn.hasValue())
+ return aReturn;
+ return OWeakObject::queryInterface(rType);
+}
+
+static void checkInterface(css::uno::Type const& rType)
+{
+ if (css::uno::TypeClass_INTERFACE != rType.getTypeClass())
+ {
+ OUString msg("querying for interface \"" + rType.getTypeName() + "\": no interface type!");
+ SAL_WARN("cppuhelper", msg);
+ throw css::uno::RuntimeException(msg);
+ }
+}
+
+static bool isXInterface(rtl_uString* pStr)
+{
+ return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
+}
+
+static bool td_equals(typelib_TypeDescriptionReference const* pTDR1,
+ typelib_TypeDescriptionReference const* pTDR2)
+{
+ return ((pTDR1 == pTDR2)
+ || OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
+}
+
+static cppu::type_entry* getTypeEntries(cppu::class_data* cd)
+{
+ cppu::type_entry* pEntries = cd->m_typeEntries;
+ if (!cd->m_storedTypeRefs) // not inited?
+ {
+ static std::mutex aMutex;
+ std::scoped_lock guard(aMutex);
+ if (!cd->m_storedTypeRefs) // not inited?
+ {
+ // get all types
+ for (sal_Int32 n = cd->m_nTypes; n--;)
+ {
+ cppu::type_entry* pEntry = &pEntries[n];
+ css::uno::Type const& rType = (*pEntry->m_type.getCppuType)(nullptr);
+ OSL_ENSURE(rType.getTypeClass() == css::uno::TypeClass_INTERFACE,
+ "### wrong helper init: expected interface!");
+ OSL_ENSURE(
+ !isXInterface(rType.getTypeLibType()->pTypeName),
+ "### want to implement XInterface: template argument is XInterface?!?!?!");
+ if (rType.getTypeClass() != css::uno::TypeClass_INTERFACE)
+ {
+ OUString msg("type \"" + rType.getTypeName() + "\" is no interface type!");
+ SAL_WARN("cppuhelper", msg);
+ throw css::uno::RuntimeException(msg);
+ }
+ // ref is statically held by getCppuType()
+ pEntry->m_type.typeRef = rType.getTypeLibType();
+ }
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ cd->m_storedTypeRefs = true;
+ }
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ return pEntries;
+}
+
+static void* makeInterface(sal_IntPtr nOffset, void* that)
+{
+ return (static_cast<char*>(that) + nOffset);
+}
+
+static bool recursivelyFindType(typelib_TypeDescriptionReference const* demandedType,
+ typelib_InterfaceTypeDescription const* type, sal_IntPtr* offset)
+{
+ // This code assumes that the vtables of a multiple-inheritance class (the
+ // offset amount by which to adjust the this pointer) follow one another in
+ // the object layout, and that they contain slots for the inherited classes
+ // in a specific order. In theory, that need not hold for any given
+ // platform; in practice, it seems to work well on all supported platforms:
+next:
+ for (sal_Int32 i = 0; i < type->nBaseTypes; ++i)
+ {
+ if (i > 0)
+ {
+ *offset += sizeof(void*);
+ }
+ typelib_InterfaceTypeDescription const* base = type->ppBaseTypes[i];
+ // ignore XInterface:
+ if (base->nBaseTypes > 0)
+ {
+ if (td_equals(reinterpret_cast<typelib_TypeDescriptionReference const*>(base),
+ demandedType))
+ {
+ return true;
+ }
+ // Profiling showed that it is important to speed up the common case
+ // of only one base:
+ if (type->nBaseTypes == 1)
+ {
+ type = base;
+ goto next;
+ }
+ if (recursivelyFindType(demandedType, base, offset))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void* queryDeepNoXInterface(typelib_TypeDescriptionReference const* pDemandedTDR,
+ cppu::class_data* cd, void* that)
+{
+ cppu::type_entry* pEntries = getTypeEntries(cd);
+ sal_Int32 nTypes = cd->m_nTypes;
+ sal_Int32 n;
+
+ // try top interfaces without getting td
+ for (n = 0; n < nTypes; ++n)
+ {
+ if (td_equals(pEntries[n].m_type.typeRef, pDemandedTDR))
+ {
+ return makeInterface(pEntries[n].m_offset, that);
+ }
+ }
+ // query deep getting td
+ for (n = 0; n < nTypes; ++n)
+ {
+ typelib_TypeDescription* pTD = nullptr;
+ TYPELIB_DANGER_GET(&pTD, pEntries[n].m_type.typeRef);
+ if (pTD)
+ {
+ // exclude top (already tested) and bottom (XInterface) interface
+ OSL_ENSURE(reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD)->nBaseTypes > 0,
+ "### want to implement XInterface:"
+ " template argument is XInterface?!?!?!");
+ sal_IntPtr offset = pEntries[n].m_offset;
+ bool found = recursivelyFindType(
+ pDemandedTDR, reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD), &offset);
+ TYPELIB_DANGER_RELEASE(pTD);
+ if (found)
+ {
+ return makeInterface(offset, that);
+ }
+ }
+ else
+ {
+ OUString msg("cannot get type description for type \""
+ + OUString::unacquired(&pEntries[n].m_type.typeRef->pTypeName) + "\"!");
+ SAL_WARN("cppuhelper", msg);
+ throw css::uno::RuntimeException(msg);
+ }
+ }
+ return nullptr;
+}
+
+css::uno::Any WeakComponentImplHelper_query(css::uno::Type const& rType, cppu::class_data* cd,
+ WeakComponentImplHelperBase2* pBase)
+{
+ checkInterface(rType);
+ typelib_TypeDescriptionReference* pTDR = rType.getTypeLibType();
+
+ // shortcut XInterface to WeakComponentImplHelperBase
+ if (!isXInterface(pTDR->pTypeName))
+ {
+ void* p = queryDeepNoXInterface(pTDR, cd, pBase);
+ if (p)
+ {
+ return css::uno::Any(&p, pTDR);
+ }
+ }
+ return pBase->cppuhelper::WeakComponentImplHelperBase2::queryInterface(rType);
+}
+
+} // namespace cppuextra
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/cppuhelper/source/component_context.cxx b/cppuhelper/source/component_context.cxx
index 81c7d306fae3..21604a6bcd1b 100644
--- a/cppuhelper/source/component_context.cxx
+++ b/cppuhelper/source/component_context.cxx
@@ -31,6 +31,7 @@
#include <cppuhelper/compbase.hxx>
#include <cppuhelper/component_context.hxx>
#include <cppuhelper/implbase.hxx>
+#include <compbase2.hxx>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
@@ -57,20 +58,24 @@ using namespace ::com::sun::star;
namespace cppu
{
-static void try_dispose( Reference< XInterface > const & xInstance )
+static void try_dispose( std::unique_lock<std::mutex>& rGuard, Reference< XInterface > const & xInstance )
{
Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
if (xComp.is())
{
+ rGuard.unlock();
xComp->dispose();
+ rGuard.lock();
}
}
-static void try_dispose( Reference< lang::XComponent > const & xComp )
+static void try_dispose( std::unique_lock<std::mutex>& rGuard, Reference< lang::XComponent > const & xComp )
{
if (xComp.is())
{
+ rGuard.unlock();
xComp->dispose();
+ rGuard.lock();
}
}
@@ -116,8 +121,7 @@ void DisposingForwarder::disposing( lang::EventObject const & )
namespace {
class ComponentContext
- : private cppu::BaseMutex
- , public WeakComponentImplHelper< XComponentContext,
+ : public cppuhelper::WeakComponentImplHelper2< XComponentContext,
container::XNameContainer >
{
protected:
@@ -141,7 +145,7 @@ protected:
protected:
Any lookupMap( OUString const & rName );
- virtual void SAL_CALL disposing() override;
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
public:
ComponentContext(
ContextEntry_Init const * pEntries, sal_Int32 nEntries,
@@ -179,7 +183,7 @@ void ComponentContext::insertByName(
/* lateInit_: */
name.startsWith( "/singletons/" ) &&
!element.hasValue() );
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
std::pair<t_map::iterator, bool> insertion( m_map.emplace(
name, entry ) );
if (! insertion.second)
@@ -191,7 +195,7 @@ void ComponentContext::insertByName(
void ComponentContext::removeByName( OUString const & name )
{
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
t_map::iterator iFind( m_map.find( name ) );
if (iFind == m_map.end())
throw container::NoSuchElementException(
@@ -206,7 +210,7 @@ void ComponentContext::removeByName( OUString const & name )
void ComponentContext::replaceByName(
OUString const & name, Any const & element )
{
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
t_map::iterator iFind( m_map.find( name ) );
if (iFind == m_map.end())
throw container::NoSuchElementException(
@@ -235,14 +239,14 @@ Any ComponentContext::getByName( OUString const & name )
Sequence<OUString> ComponentContext::getElementNames()
{
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
return comphelper::mapKeysToSequence(m_map);
}
sal_Bool ComponentContext::hasByName( OUString const & name )
{
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
return m_map.find( name ) != m_map.end();
}
@@ -256,14 +260,14 @@ Type ComponentContext::getElementType()
sal_Bool ComponentContext::hasElements()
{
- MutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
return ! m_map.empty();
}
Any ComponentContext::lookupMap( OUString const & rName )
{
- ResettableMutexGuard guard( m_aMutex );
+ std::unique_lock guard( m_aMutex );
t_map::iterator iFind( m_map.find( rName ) );
if (iFind == m_map.end())
return Any();
@@ -274,7 +278,7 @@ Any ComponentContext::lookupMap( OUString const & rName )
// late init singleton entry
Reference< XInterface > xInstance;
- guard.clear();
+ guard.unlock();
try
{
@@ -334,7 +338,7 @@ Any ComponentContext::lookupMap( OUString const & rName )
"cppuhelper", "no service object raising singleton " << rName);
Any ret;
- guard.reset();
+ guard.lock();
iFind = m_map.find( rName );
if (iFind != m_map.end())
{
@@ -347,9 +351,8 @@ Any ComponentContext::lookupMap( OUString const & rName )
}
ret = rEntry.value;
}
- guard.clear();
if (ret != xInstance) {
- try_dispose( xInstance );
+ try_dispose( guard, xInstance );
}
return ret;
}
@@ -384,7 +387,7 @@ Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
return m_xSMgr;
}
-void ComponentContext::disposing()
+void ComponentContext::disposing(std::unique_lock<std::mutex>& rGuard)
{
Reference< lang::XComponent > xTDMgr, xAC; // to be disposed separately
@@ -398,7 +401,6 @@ void ComponentContext::disposing()
if (rEntry.lateInit)
{
// late init
- MutexGuard guard( m_aMutex );
if (rEntry.lateInit)
{
rEntry.value.clear(); // release factory
@@ -421,19 +423,21 @@ void ComponentContext::disposing()
}
else // dispose immediately
{
+ rGuard.unlock();
xComp->dispose();
+ rGuard.lock();
}
}
}
}
// dispose service manager
- try_dispose( m_xSMgr );
+ try_dispose( rGuard, m_xSMgr );
m_xSMgr.clear();
// dispose ac
- try_dispose( xAC );
+ try_dispose( rGuard, xAC );
// dispose tdmgr; revokes callback from cppu runtime
- try_dispose( xTDMgr );
+ try_dispose( rGuard, xTDMgr );
m_map.clear();
@@ -459,8 +463,7 @@ void ComponentContext::disposing()
ComponentContext::ComponentContext(
ContextEntry_Init const * pEntries, sal_Int32 nEntries,
Reference< XComponentContext > const & xDelegate )
- : WeakComponentImplHelper( m_aMutex ),
- m_xDelegate( xDelegate )
+ : m_xDelegate( xDelegate )
{
for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
{
diff --git a/cppuhelper/source/unoimplbase.cxx b/cppuhelper/source/unoimplbase.cxx
new file mode 100644
index 000000000000..be3d423d24c2
--- /dev/null
+++ b/cppuhelper/source/unoimplbase.cxx
@@ -0,0 +1,27 @@
+/* -*- 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 <unoimplbase.hxx>
+
+namespace cppuhelper
+{
+UnoImplBase::~UnoImplBase() {}
+
+} // end namespace cppuextra
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */