Move KServiceTypeTrader query for Scripts into a thread
Searching for the scripts to load is performed in an own thread including unloading of already loaded scripts which no longer should be loaded. To ensure that two threads are not trying to load/unload at the same time a mutex is added to protect the list of loaded scripts. REVIEW: 104768
This commit is contained in:
parent
bb5dce0e3b
commit
6cbdfd3cd5
2 changed files with 54 additions and 4 deletions
|
@ -37,7 +37,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kdeclarative.h>
|
||||
// Qt
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtCore/QFutureWatcher>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QtConcurrentRun>
|
||||
#include <QtDeclarative/QDeclarativeContext>
|
||||
#include <QtDeclarative/QDeclarativeEngine>
|
||||
#include <QtDeclarative/QDeclarativeView>
|
||||
|
@ -248,6 +250,7 @@ void KWin::DeclarativeScript::run()
|
|||
|
||||
KWin::Scripting::Scripting(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_scriptsLock(new QMutex(QMutex::Recursive))
|
||||
{
|
||||
QDBusConnection::sessionBus().registerObject("/Scripting", this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables);
|
||||
QDBusConnection::sessionBus().registerService("org.kde.kwin.Scripting");
|
||||
|
@ -256,11 +259,20 @@ KWin::Scripting::Scripting(QObject *parent)
|
|||
}
|
||||
|
||||
void KWin::Scripting::start()
|
||||
{
|
||||
// perform querying for the services in a thread
|
||||
QFutureWatcher<LoadScriptList> *watcher = new QFutureWatcher<LoadScriptList>(this);
|
||||
connect(watcher, SIGNAL(finished()), this, SLOT(slotScriptsQueried()));
|
||||
watcher->setFuture(QtConcurrent::run(this, &KWin::Scripting::queryScriptsToLoad));
|
||||
}
|
||||
|
||||
LoadScriptList KWin::Scripting::queryScriptsToLoad()
|
||||
{
|
||||
KSharedConfig::Ptr _config = KGlobal::config();
|
||||
KConfigGroup conf(_config, "Plugins");
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("KWin/Script");
|
||||
LoadScriptList scriptsToLoad;
|
||||
|
||||
foreach (const KService::Ptr & service, offers) {
|
||||
KPluginInfo plugininfo(service);
|
||||
|
@ -285,18 +297,37 @@ void KWin::Scripting::start()
|
|||
kDebug(1212) << "Could not find script file for " << pluginName;
|
||||
continue;
|
||||
}
|
||||
if (javaScript) {
|
||||
loadScript(file, pluginName);
|
||||
} else if (declarativeScript) {
|
||||
loadDeclarativeScript(file, pluginName);
|
||||
scriptsToLoad << qMakePair(javaScript, qMakePair(file, pluginName));
|
||||
}
|
||||
return scriptsToLoad;
|
||||
}
|
||||
|
||||
void KWin::Scripting::slotScriptsQueried()
|
||||
{
|
||||
QFutureWatcher<LoadScriptList> *watcher = dynamic_cast< QFutureWatcher<LoadScriptList>* >(sender());
|
||||
if (!watcher) {
|
||||
// slot invoked not from a FutureWatcher
|
||||
return;
|
||||
}
|
||||
|
||||
LoadScriptList scriptsToLoad = watcher->result();
|
||||
for (LoadScriptList::const_iterator it = scriptsToLoad.constBegin();
|
||||
it != scriptsToLoad.constEnd();
|
||||
++it) {
|
||||
if (it->first) {
|
||||
loadScript(it->second.first, it->second.second);
|
||||
} else {
|
||||
loadDeclarativeScript(it->second.first, it->second.second);
|
||||
}
|
||||
}
|
||||
|
||||
runScripts();
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
bool KWin::Scripting::isScriptLoaded(const QString &pluginName) const
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
foreach (AbstractScript *script, scripts) {
|
||||
if (script->pluginName() == pluginName) {
|
||||
return true;
|
||||
|
@ -307,6 +338,7 @@ bool KWin::Scripting::isScriptLoaded(const QString &pluginName) const
|
|||
|
||||
bool KWin::Scripting::unloadScript(const QString &pluginName)
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
foreach (AbstractScript *script, scripts) {
|
||||
if (script->pluginName() == pluginName) {
|
||||
script->deleteLater();
|
||||
|
@ -318,6 +350,7 @@ bool KWin::Scripting::unloadScript(const QString &pluginName)
|
|||
|
||||
void KWin::Scripting::runScripts()
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
for (int i = 0; i < scripts.size(); i++) {
|
||||
scripts.at(i)->run();
|
||||
}
|
||||
|
@ -325,11 +358,13 @@ void KWin::Scripting::runScripts()
|
|||
|
||||
void KWin::Scripting::scriptDestroyed(QObject *object)
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
scripts.removeAll(static_cast<KWin::Script*>(object));
|
||||
}
|
||||
|
||||
int KWin::Scripting::loadScript(const QString &filePath, const QString& pluginName)
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
if (isScriptLoaded(pluginName)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -342,6 +377,7 @@ int KWin::Scripting::loadScript(const QString &filePath, const QString& pluginNa
|
|||
|
||||
int KWin::Scripting::loadDeclarativeScript(const QString& filePath, const QString& pluginName)
|
||||
{
|
||||
QMutexLocker locker(m_scriptsLock.data());
|
||||
if (isScriptLoaded(pluginName)) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
class QAction;
|
||||
class QDeclarativeView;
|
||||
class QMutex;
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
class KConfigGroup;
|
||||
|
||||
/// @c true == javascript, @c false == qml
|
||||
typedef QList< QPair<bool, QPair<QString, QString > > > LoadScriptList;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class WorkspaceWrapper;
|
||||
|
@ -147,6 +151,10 @@ class Scripting : public QObject
|
|||
private:
|
||||
QStringList scriptList;
|
||||
QList<KWin::AbstractScript*> scripts;
|
||||
/**
|
||||
* Lock to protect the scripts member variable.
|
||||
**/
|
||||
QScopedPointer<QMutex> m_scriptsLock;
|
||||
|
||||
// Preferably call ONLY at load time
|
||||
void runScripts();
|
||||
|
@ -162,6 +170,12 @@ public:
|
|||
public Q_SLOTS:
|
||||
void scriptDestroyed(QObject *object);
|
||||
void start();
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotScriptsQueried();
|
||||
|
||||
private:
|
||||
LoadScriptList queryScriptsToLoad();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue