Cache accessibility plugins.
Profiling shows that the cost of QAcccessible:: queryAccessibleInterface is dominated by plugin loading. (json parsing etc.) Cache QAccessiblePlugin per class. Also cache the fact that no plugin is found for a certain class. This speeds up the average queryAccessibleInterface call by a factor of 10X Change-Id: Iab6d052dec499a2203d1dcc4672a8a543b279239 Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
This commit is contained in:
parent
3f374afaae
commit
818c544d6b
@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
#include <QtCore/qmetaobject.h>
|
#include <QtCore/qmetaobject.h>
|
||||||
|
#include <QtCore/qhash.h>
|
||||||
#include <private/qfactoryloader_p.h>
|
#include <private/qfactoryloader_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -430,6 +431,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
|
Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
|
||||||
|
typedef QHash<QString, QAccessiblePlugin*> QAccessiblePluginsHash;
|
||||||
|
Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins);
|
||||||
|
|
||||||
QAccessible::UpdateHandler QAccessible::updateHandler = 0;
|
QAccessible::UpdateHandler QAccessible::updateHandler = 0;
|
||||||
QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
|
QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
|
||||||
@ -580,9 +583,13 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
|
|||||||
if (!object)
|
if (!object)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Create a QAccessibleInterface for the object class. Start by the most
|
||||||
|
// derived class and walk up the class hierarchy.
|
||||||
const QMetaObject *mo = object->metaObject();
|
const QMetaObject *mo = object->metaObject();
|
||||||
while (mo) {
|
while (mo) {
|
||||||
const QString cn = QLatin1String(mo->className());
|
const QString cn = QLatin1String(mo->className());
|
||||||
|
|
||||||
|
// Check if the class has a InterfaceFactory installed.
|
||||||
for (int i = qAccessibleFactories()->count(); i > 0; --i) {
|
for (int i = qAccessibleFactories()->count(); i > 0; --i) {
|
||||||
InterfaceFactory factory = qAccessibleFactories()->at(i - 1);
|
InterfaceFactory factory = qAccessibleFactories()->at(i - 1);
|
||||||
if (QAccessibleInterface *iface = factory(cn, object))
|
if (QAccessibleInterface *iface = factory(cn, object))
|
||||||
@ -590,8 +597,21 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
|
|||||||
}
|
}
|
||||||
#ifndef QT_NO_ACCESSIBILITY
|
#ifndef QT_NO_ACCESSIBILITY
|
||||||
#ifndef QT_NO_LIBRARY
|
#ifndef QT_NO_LIBRARY
|
||||||
if (QAccessibleInterface * iface = qLoadPlugin1<QAccessibleInterface, QAccessiblePlugin>(loader(), cn, object))
|
// Find a QAccessiblePlugin (factory) for the class name. If there's
|
||||||
return iface;
|
// no entry in the cache try to create it using the plugin loader.
|
||||||
|
if (!qAccessiblePlugins()->contains(cn)) {
|
||||||
|
QAccessiblePlugin *factory = 0; // 0 means "no plugin found". This is cached as well.
|
||||||
|
const int index = loader()->indexOf(cn);
|
||||||
|
if (index != -1)
|
||||||
|
factory = qobject_cast<QAccessiblePlugin *>(loader()->instance(index));
|
||||||
|
qAccessiblePlugins()->insert(cn, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point the cache should contain a valid factory pointer or 0:
|
||||||
|
Q_ASSERT(qAccessiblePlugins()->contains(cn));
|
||||||
|
QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn);
|
||||||
|
if (factory)
|
||||||
|
return factory->create(cn, object);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
mo = mo->superClass();
|
mo = mo->superClass();
|
||||||
|
Loading…
Reference in New Issue
Block a user