summaryrefslogtreecommitdiff
path: root/stoc
diff options
context:
space:
mode:
authorMatthew J. Francis <mjay.francis@gmail.com>2015-07-06 08:09:24 +0800
committerStephan Bergmann <sbergman@redhat.com>2015-07-08 16:51:54 +0200
commit61b1697069c50ff72339d4592add42ab72b03243 (patch)
tree84787febec55351abbec7688cef601de310dc32a /stoc
parentb3e645cde951906d883f015d342f85fc0eedb2ec (diff)
Reduce the amount of up front work in performing introspection
Previously, when using PyUNO over a remote bridge, each remote call which returned an object could result in 50+ further calls to query interfaces on the result, regardless of whether and how the object was then used. The majority of these queries were made under css.script.Invocation to pre-cache certain information about the returned object. By making better use of available information to eliminate interface queries which are certain to fail, and lazily acquiring those interfaces which are required, remote scripting is significantly accelerated. In general, this also gives a small speedup for local scripting. Change-Id: I4f36da6b5f09cb0d22f21291f05fbea2ae7ae697 Signed-off-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'stoc')
-rw-r--r--stoc/source/inspect/introspection.cxx245
1 files changed, 199 insertions, 46 deletions
diff --git a/stoc/source/inspect/introspection.cxx b/stoc/source/inspect/introspection.cxx
index e6b9110b7607..cfa7085f2901 100644
--- a/stoc/source/inspect/introspection.cxx
+++ b/stoc/source/inspect/introspection.cxx
@@ -162,6 +162,7 @@ class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
{
friend class Implementation;
friend class ImplIntrospectionAccess;
+ friend class ImplIntrospectionAdapter;
// Holding CoreReflection
Reference< XIdlReflection > mxCoreReflection;
@@ -194,8 +195,16 @@ class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
sal_Int32 mnAttributePropCount;
sal_Int32 mnMethodPropCount;
- // Flag, if a FastPropertySet is supported
+ // Flags which indicate if various interfaces are present
bool mbFastPropSet;
+ bool mbPropertySet;
+ bool mbElementAccess;
+ bool mbNameAccess;
+ bool mbNameContainer;
+ bool mbIndexAccess;
+ bool mbIndexContainer;
+ bool mbEnumerationAccess;
+ bool mbIdlArray;
// Original-Handles of FastPropertySets
sal_Int32* mpOrgPropertyHandleArray;
@@ -261,6 +270,15 @@ IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlR
maPropertyConceptSeq.realloc( ARRAY_SIZE_STEP );
mbFastPropSet = false;
+ mbPropertySet = false;
+ mbElementAccess = false;
+ mbNameAccess = false;
+ mbNameContainer = false;
+ mbIndexAccess = false;
+ mbIndexContainer = false;
+ mbEnumerationAccess = false;
+ mbIdlArray = false;
+
mpOrgPropertyHandleArray = NULL;
mnPropCount = 0;
@@ -772,6 +790,9 @@ class ImplIntrospectionAdapter :
// Objekt als Interface
Reference<XInterface> mxIface;
+ // Guards the caching of queried interfaces
+ osl::Mutex m_aMutex;
+
// Original-Interfaces des Objekts
Reference<XElementAccess> mxObjElementAccess;
Reference<XNameContainer> mxObjNameContainer;
@@ -781,6 +802,14 @@ class ImplIntrospectionAdapter :
Reference<XEnumerationAccess> mxObjEnumerationAccess;
Reference<XIdlArray> mxObjIdlArray;
+ Reference<XElementAccess> getXElementAccess();
+ Reference<XNameContainer> getXNameContainer();
+ Reference<XNameAccess> getXNameAccess();
+ Reference<XIndexContainer> getXIndexContainer();
+ Reference<XIndexAccess> getXIndexAccess();
+ Reference<XEnumerationAccess> getXEnumerationAccess();
+ Reference<XIdlArray> getXIdlArray();
+
public:
ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_,
const Any& obj,
@@ -861,6 +890,112 @@ public:
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception ) SAL_OVERRIDE;
};
+Reference<XElementAccess> ImplIntrospectionAdapter::getXElementAccess()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjElementAccess.is() )
+ {
+ aGuard.clear();
+ Reference<XElementAccess> xElementAccess = Reference<XElementAccess>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjElementAccess.is() )
+ mxObjElementAccess = xElementAccess;
+ }
+ return mxObjElementAccess;
+}
+
+Reference<XNameContainer> ImplIntrospectionAdapter::getXNameContainer()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjNameContainer.is() )
+ {
+ aGuard.clear();
+ Reference<XNameContainer> xNameContainer = Reference<XNameContainer>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjNameContainer.is() )
+ mxObjNameContainer = xNameContainer;
+ }
+ return mxObjNameContainer;
+}
+
+Reference<XNameAccess> ImplIntrospectionAdapter::getXNameAccess()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjNameAccess.is() )
+ {
+ aGuard.clear();
+ Reference<XNameAccess> xNameAccess = Reference<XNameAccess>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjNameAccess.is() )
+ mxObjNameAccess = xNameAccess;
+ }
+ return mxObjNameAccess;
+}
+
+Reference<XIndexContainer> ImplIntrospectionAdapter::getXIndexContainer()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjIndexContainer.is() )
+ {
+ aGuard.clear();
+ Reference<XIndexContainer> xIndexContainer = Reference<XIndexContainer>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjIndexContainer.is() )
+ mxObjIndexContainer = xIndexContainer;
+ }
+ return mxObjIndexContainer;
+}
+
+Reference<XIndexAccess> ImplIntrospectionAdapter::getXIndexAccess()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjIndexAccess.is() )
+ {
+ aGuard.clear();
+ Reference<XIndexAccess> xIndexAccess = Reference<XIndexAccess>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjIndexAccess.is() )
+ mxObjIndexAccess = xIndexAccess;
+ }
+ return mxObjIndexAccess;
+}
+
+Reference<XEnumerationAccess> ImplIntrospectionAdapter::getXEnumerationAccess()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjEnumerationAccess.is() )
+ {
+ aGuard.clear();
+ Reference<XEnumerationAccess> xEnumerationAccess = Reference<XEnumerationAccess>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjEnumerationAccess.is() )
+ mxObjEnumerationAccess = xEnumerationAccess;
+ }
+ return mxObjEnumerationAccess;
+}
+
+Reference<XIdlArray> ImplIntrospectionAdapter::getXIdlArray()
+{
+ ResettableGuard< Mutex > aGuard( m_aMutex );
+
+ if( !mxObjIdlArray.is() )
+ {
+ aGuard.clear();
+ Reference<XIdlArray> xIdlArray = Reference<XIdlArray>::query( mxIface );
+ aGuard.reset();
+ if( !mxObjIdlArray.is() )
+ mxObjIdlArray = xIdlArray;
+ }
+ return mxObjIdlArray;
+}
+
+
ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_,
const Any& obj,
rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ )
@@ -869,17 +1004,7 @@ ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAc
// Objekt als Interfaceholen
TypeClass eType = mrInspectedObject.getValueType().getTypeClass();
if( eType == TypeClass_INTERFACE )
- {
mxIface = *static_cast<Reference< XInterface > const *>(mrInspectedObject.getValue());
-
- mxObjElementAccess = Reference<XElementAccess>::query( mxIface );
- mxObjNameAccess = Reference<XNameAccess>::query( mxIface );
- mxObjNameContainer = Reference<XNameContainer>::query( mxIface );
- mxObjIndexAccess = Reference<XIndexAccess>::query( mxIface );
- mxObjIndexContainer = Reference<XIndexContainer>::query( mxIface );
- mxObjEnumerationAccess = Reference<XEnumerationAccess>::query( mxIface );
- mxObjIdlArray = Reference<XIdlArray>::query( mxIface );
- }
}
// Methoden von XInterface
@@ -897,14 +1022,14 @@ Any SAL_CALL ImplIntrospectionAdapter::queryInterface( const Type& rType )
if( !aRet.hasValue() )
{
// Wrapper fuer die Objekt-Interfaces
- if( ( mxObjElementAccess.is() && (aRet = ::cppu::queryInterface
+ if( ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
- || ( mxObjNameAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
- || ( mxObjNameContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
- || ( mxObjIndexAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
- || ( mxObjIndexContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
- || ( mxObjEnumerationAccess .is() && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
- || ( mxObjIdlArray.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
+ || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
)
{
}
@@ -1021,121 +1146,120 @@ sal_Bool ImplIntrospectionAdapter::hasPropertyByName(const OUString& Name)
// Methoden von XElementAccess
Type ImplIntrospectionAdapter::getElementType() throw( RuntimeException, std::exception )
{
- return mxObjElementAccess->getElementType();
+ return getXElementAccess()->getElementType();
}
sal_Bool ImplIntrospectionAdapter::hasElements() throw( RuntimeException, std::exception )
{
- return mxObjElementAccess->hasElements();
+ return getXElementAccess()->hasElements();
}
// Methoden von XNameAccess
Any ImplIntrospectionAdapter::getByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
- return mxObjNameAccess->getByName( Name );
+ return getXNameAccess()->getByName( Name );
}
Sequence< OUString > ImplIntrospectionAdapter::getElementNames()
throw( RuntimeException, std::exception )
{
- return mxObjNameAccess->getElementNames();
+ return getXNameAccess()->getElementNames();
}
sal_Bool ImplIntrospectionAdapter::hasByName(const OUString& Name)
throw( RuntimeException, std::exception )
{
- return mxObjNameAccess->hasByName( Name );
+ return getXNameAccess()->hasByName( Name );
}
// Methoden von XNameContainer
void ImplIntrospectionAdapter::insertByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjNameContainer->insertByName( Name, Element );
+ getXNameContainer()->insertByName( Name, Element );
}
void ImplIntrospectionAdapter::replaceByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjNameContainer->replaceByName( Name, Element );
+ getXNameContainer()->replaceByName( Name, Element );
}
void ImplIntrospectionAdapter::removeByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjNameContainer->removeByName( Name );
+ getXNameContainer()->removeByName( Name );
}
// Methoden von XIndexAccess
// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType() const
sal_Int32 ImplIntrospectionAdapter::getCount() throw( RuntimeException, std::exception )
{
- return mxObjIndexAccess->getCount();
+ return getXIndexAccess()->getCount();
}
Any ImplIntrospectionAdapter::getByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
- return mxObjIndexAccess->getByIndex( Index );
+ return getXIndexAccess()->getByIndex( Index );
}
// Methoden von XIndexContainer
void ImplIntrospectionAdapter::insertByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjIndexContainer->insertByIndex( Index, Element );
+ getXIndexContainer()->insertByIndex( Index, Element );
}
void ImplIntrospectionAdapter::replaceByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjIndexContainer->replaceByIndex( Index, Element );
+ getXIndexContainer()->replaceByIndex( Index, Element );
}
void ImplIntrospectionAdapter::removeByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
- mxObjIndexContainer->removeByIndex( Index );
+ getXIndexContainer()->removeByIndex( Index );
}
// Methoden von XEnumerationAccess
// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
Reference<XEnumeration> ImplIntrospectionAdapter::createEnumeration() throw( RuntimeException, std::exception )
{
- return mxObjEnumerationAccess->createEnumeration();
+ return getXEnumerationAccess()->createEnumeration();
}
// Methoden von XIdlArray
void ImplIntrospectionAdapter::realloc(Any& array, sal_Int32 length)
throw( IllegalArgumentException, RuntimeException, std::exception )
{
- mxObjIdlArray->realloc( array, length );
+ getXIdlArray()->realloc( array, length );
}
sal_Int32 ImplIntrospectionAdapter::getLen(const Any& array)
throw( IllegalArgumentException, RuntimeException, std::exception )
{
- return mxObjIdlArray->getLen( array );
+ return getXIdlArray()->getLen( array );
}
Any ImplIntrospectionAdapter::get(const Any& array, sal_Int32 index)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception )
{
- return mxObjIdlArray->get( array, index );
+ return getXIdlArray()->get( array, index );
}
void ImplIntrospectionAdapter::set(Any& array, sal_Int32 index, const Any& value)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception )
{
- mxObjIdlArray->set( array, index, value );
+ getXIdlArray()->set( array, index, value );
}
//*** Implementation von ImplIntrospectionAccess ***
-
// Methoden von XIntrospectionAccess
sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
throw( RuntimeException, std::exception )
@@ -1347,6 +1471,7 @@ Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type
{
// Gibt es schon einen Adapter?
Reference< XInterface > xAdapter( maAdapter );
+
if( !xAdapter.is() )
{
xAdapter = *( new ImplIntrospectionAdapter( this, maInspectedObject, mpStaticImpl ) );
@@ -1620,6 +1745,7 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
Reference<XIdlClass> xImplClass;
Reference<XPropertySetInfo> xPropSetInfo;
Reference<XPropertySet> xPropSet;
+ bool bHasPropertySet = false;
// Look for interfaces XTypeProvider and PropertySet
if( eType == TypeClass_INTERFACE )
@@ -1637,7 +1763,10 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
const Type* pTypes = SupportedTypesSeq.getConstArray();
for( sal_Int32 i = 0 ; i < nTypeCount ; i++ )
{
- pClasses[i] = reflection->forName(pTypes[i].getTypeName());
+ OUString typeName( pTypes[i].getTypeName() );
+ pClasses[i] = reflection->forName( typeName );
+ if( !bHasPropertySet && typeName == "com.sun.star.beans.XPropertySet" )
+ bHasPropertySet = true;
}
// TODO: Caching!
}
@@ -1651,7 +1780,8 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
SupportedClassSeq[0] = xImplClass;
}
- xPropSet = Reference<XPropertySet>::query( x );
+ if ( bHasPropertySet )
+ xPropSet = Reference<XPropertySet>::query( x );
// Jetzt versuchen, das PropertySetInfo zu bekommen
if( xPropSet.is() )
xPropSetInfo = xPropSet->getPropertySetInfo();
@@ -1660,7 +1790,7 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
}
if (xTypeProvider.is()) {
- TypeKey key(xPropSetInfo, xTypeProvider->getTypes());
+ TypeKey key(xPropSetInfo, SupportedTypesSeq);
osl::MutexGuard g(m_aMutex);
if (rBHelper.bDisposed || rBHelper.bInDispose) {
@@ -1700,6 +1830,8 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
if( !pAccess.is() )
pAccess = new IntrospectionAccessStatic_Impl( reflection );
+ pAccess->mbPropertySet = bHasPropertySet;
+
// Referenzen auf wichtige Daten von pAccess
sal_Int32& rPropCount = pAccess->mnPropCount;
IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
@@ -1949,22 +2081,43 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
rMethodConcept_i |= ( NAMECONTAINER |
INDEXCONTAINER |
ENUMERATION );
+ pAccess->mbElementAccess = true;
} else if ((className
- == "com.sun.star.container.XNameContainer")
- || (className
- == "com.sun.star.container.XNameAccess"))
+ == "com.sun.star.container.XNameContainer"))
{
rMethodConcept_i |= NAMECONTAINER;
+ pAccess->mbNameContainer = true;
+ pAccess->mbNameAccess = true;
+ pAccess->mbElementAccess = true;
} else if ((className
- == "com.sun.star.container.XIndexContainer")
- || (className
- == "com.sun.star.container.XIndexAccess"))
+ == "com.sun.star.container.XNameAccess"))
+ {
+ rMethodConcept_i |= NAMECONTAINER;
+ pAccess->mbNameAccess = true;
+ pAccess->mbElementAccess = true;
+ } else if ((className
+ == "com.sun.star.container.XIndexContainer"))
{
rMethodConcept_i |= INDEXCONTAINER;
+ pAccess->mbIndexContainer = true;
+ pAccess->mbIndexAccess = true;
+ pAccess->mbElementAccess = true;
+ } else if ((className
+ == "com.sun.star.container.XIndexAccess"))
+ {
+ rMethodConcept_i |= INDEXCONTAINER;
+ pAccess->mbIndexAccess = true;
+ pAccess->mbElementAccess = true;
} else if (className
== "com.sun.star.container.XEnumerationAccess")
{
rMethodConcept_i |= ENUMERATION;
+ pAccess->mbEnumerationAccess = true;
+ pAccess->mbElementAccess = true;
+ } else if (className
+ == "com.sun.star.reflection.XIdlArray")
+ {
+ pAccess->mbIdlArray = true;
}
// Wenn der Name zu kurz ist, wird's sowieso nichts