Skip to content
Snippets Groups Projects
Commit 1860b022 authored by Gigg, Martyn Anthony's avatar Gigg, Martyn Anthony
Browse files

Use a dedicated thread for each script instance. Refs #5766

parent 922cea72
No related branches found
No related tags found
No related merge requests found
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <QVariant> #include <QVariant>
#include <QMessageBox> #include <QMessageBox>
#include <QtConcurrentRun>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
...@@ -63,6 +62,7 @@ namespace ...@@ -63,6 +62,7 @@ namespace
PyObject_CallMethod(scriptObj, "lineNumberChanged", "O i", frame->f_code->co_filename, frame->f_lineno); PyObject_CallMethod(scriptObj, "lineNumberChanged", "O i", frame->f_code->co_filename, frame->f_lineno);
return retcode; return retcode;
} }
} }
...@@ -531,16 +531,9 @@ QVariant PythonScript::evaluateImpl() ...@@ -531,16 +531,9 @@ QVariant PythonScript::evaluateImpl()
bool PythonScript::executeImpl() bool PythonScript::executeImpl()
{ {
emit startedSerial("");
return executeString(); return executeString();
} }
QFuture<bool> PythonScript::executeAsyncImpl()
{
emit startedAsync("");
return QtConcurrent::run(this, &PythonScript::executeString);
}
/// Performs the call to Python /// Performs the call to Python
bool PythonScript::executeString() bool PythonScript::executeString()
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
class ScriptingEnv; class ScriptingEnv;
class PythonScripting; class PythonScripting;
struct _sipWrapperType; struct _sipWrapperType;
...@@ -144,6 +145,7 @@ private: ...@@ -144,6 +145,7 @@ private:
QString m_path; QString m_path;
}; };
inline PythonScripting * pythonEnv() const { return m_pythonEnv; } inline PythonScripting * pythonEnv() const { return m_pythonEnv; }
void initialize(const QString & name, QObject *context); void initialize(const QString & name, QObject *context);
void beginStdoutRedirect(); void beginStdoutRedirect();
...@@ -156,8 +158,6 @@ private: ...@@ -156,8 +158,6 @@ private:
QVariant evaluateImpl(); QVariant evaluateImpl();
/// Execute the current code and return a boolean indicating success/failure /// Execute the current code and return a boolean indicating success/failure
bool executeImpl(); bool executeImpl();
/// Execute the code asynchronously, returning immediately after the execution has started
QFuture<bool> executeAsyncImpl();
/// Performs the call to Python from a string /// Performs the call to Python from a string
bool executeString(); bool executeString();
......
...@@ -30,24 +30,25 @@ ...@@ -30,24 +30,25 @@
#include "ScriptingEnv.h" #include "ScriptingEnv.h"
#include <QRegExp> #include <QRegExp>
Script::Script(ScriptingEnv *env, const QString &name, Script::Script(ScriptingEnv *env, const QString &name,
const InteractionType interact, QObject * context) const InteractionType interact, QObject * context)
: QObject(), m_env(env), m_name() , m_context(context), : QObject(), m_env(env), m_name() , m_context(context),
m_redirectOutput(true), m_reportProgress(false), m_interactMode(interact), m_redirectOutput(true), m_reportProgress(false), m_interactMode(interact),
m_execMode(NotExecuting) m_execMode(NotExecuting), m_execThread(new ScriptThread(*this))
{ {
m_env->incref(); m_env->incref();
setName(name); setName(name);
connect(this, SIGNAL(startedSerial(const QString &)), this, SLOT(setExecutingSerialised())); connect(this, SIGNAL(started(const QString &)), this, SLOT(setIsRunning()));
connect(this, SIGNAL(startedAsync(const QString &)), this, SLOT(setExecutingAsync()));
connect(this, SIGNAL(finished(const QString &)), this, SLOT(setNotExecuting())); connect(this, SIGNAL(finished(const QString &)), this, SLOT(setNotExecuting()));
connect(this, SIGNAL(error(const QString &, const QString &, int)), this, SLOT(setNotExecuting())); connect(this, SIGNAL(error(const QString &, const QString &, int)), this, SLOT(setNotExecuting()));
} }
Script::~Script() Script::~Script()
{ {
delete m_execThread;
m_env->decref(); m_env->decref();
} }
...@@ -85,6 +86,7 @@ QVariant Script::evaluate(const ScriptCode & code) ...@@ -85,6 +86,7 @@ QVariant Script::evaluate(const ScriptCode & code)
bool Script::execute(const ScriptCode & code) bool Script::execute(const ScriptCode & code)
{ {
setupCode(code); setupCode(code);
emit started("");
return this->executeImpl(); return this->executeImpl();
} }
...@@ -92,7 +94,8 @@ bool Script::execute(const ScriptCode & code) ...@@ -92,7 +94,8 @@ bool Script::execute(const ScriptCode & code)
QFuture<bool> Script::executeAsync(const ScriptCode & code) QFuture<bool> Script::executeAsync(const ScriptCode & code)
{ {
setupCode(code); setupCode(code);
return this->executeAsyncImpl(); m_execThread->start();
return m_execThread->future();
} }
...@@ -102,15 +105,10 @@ void Script::setNotExecuting() ...@@ -102,15 +105,10 @@ void Script::setNotExecuting()
m_execMode = NotExecuting; m_execMode = NotExecuting;
} }
/// Sets the execution mode to Serialised /// Sets the execution mode to Running to indicate something is running
void Script::setExecutingSerialised() void Script::setIsRunning()
{
m_execMode = Serialised;
}
/// Sets the execution mode to Serialised
void Script::setExecutingAsync()
{ {
m_execMode = Asynchronous; m_execMode = Running;
} }
/** /**
......
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
#ifndef SCRIPT_H #ifndef SCRIPT_H
#define SCRIPT_H #define SCRIPT_H
#include <QVariant>
#include <QString>
#include <QStringList>
#include <QEvent> #include <QEvent>
#include <QFuture> #include <QFuture>
#include <QThread>
#include <QString>
#include <QStringList>
#include <QVariant>
#include "ScriptCode.h" #include "ScriptCode.h"
...@@ -56,7 +57,7 @@ class Script : public QObject ...@@ -56,7 +57,7 @@ class Script : public QObject
/// Interaction type /// Interaction type
enum InteractionType {Interactive, NonInteractive}; enum InteractionType {Interactive, NonInteractive};
/// Execution mode /// Execution mode
enum ExecutionMode {Serialised, Asynchronous, NotExecuting}; enum ExecutionMode {Serialised, Asynchronous, Running, NotExecuting};
/// Constructor /// Constructor
Script(ScriptingEnv *env, const QString &name, const InteractionType interact, Script(ScriptingEnv *env, const QString &name, const InteractionType interact,
...@@ -106,10 +107,8 @@ public slots: ...@@ -106,10 +107,8 @@ public slots:
/// Sets the execution mode to NotExecuting /// Sets the execution mode to NotExecuting
void setNotExecuting(); void setNotExecuting();
/// Sets the execution mode to Serialised /// Sets the execution mode to Running to indicate something is running
void setExecutingSerialised(); void setIsRunning();
/// Sets the execution mode to Serialised
void setExecutingAsync();
// local variables // local variables
virtual bool setQObject(QObject*, const char*) { return false; } virtual bool setQObject(QObject*, const char*) { return false; }
...@@ -119,10 +118,6 @@ public slots: ...@@ -119,10 +118,6 @@ public slots:
signals: signals:
/// A signal defining when this script has started executing /// A signal defining when this script has started executing
void started(const QString & message); void started(const QString & message);
/// A separate signal defining when this script has started executing serial running
void startedSerial(const QString & message);
/// A separate signal defining when this script has started executing asynchronously
void startedAsync(const QString & message);
/// A signal defining when this script has completed successfully /// A signal defining when this script has completed successfully
void finished(const QString & message); void finished(const QString & message);
/// signal an error condition / exception /// signal an error condition / exception
...@@ -147,10 +142,41 @@ protected: ...@@ -147,10 +142,41 @@ protected:
virtual QVariant evaluateImpl() = 0; virtual QVariant evaluateImpl() = 0;
/// Execute the Code, returning false on an error / exception. /// Execute the Code, returning false on an error / exception.
virtual bool executeImpl() = 0; virtual bool executeImpl() = 0;
/// Execute the code asynchronously, returning immediately after the execution has started
virtual QFuture<bool> executeAsyncImpl() = 0;
private: private:
/**
* Worker thread for the asynchronous exec calls
*/
class ScriptThread : public QThread
{
public:
ScriptThread(Script & script)
: QThread(), m_script(script), m_future()
{}
QFuture<bool> future()
{
return m_future;
}
void run()
{
QFutureInterface<bool> *progressObject(new QFutureInterface<bool>);
m_future = progressObject->future();
progressObject->reportStarted();
const bool result = m_script.execute(m_script.scriptCode());
progressObject->reportResult(result, 0);
progressObject->reportFinished();
delete progressObject;
}
private:
Script & m_script;
QFuture<bool> m_future;
};
/// Setup the code from a script code object /// Setup the code from a script code object
void setupCode(const ScriptCode & code); void setupCode(const ScriptCode & code);
/// Normalise line endings for the given code. The Python C/API does not seem to like CRLF endings so normalise to just LF /// Normalise line endings for the given code. The Python C/API does not seem to like CRLF endings so normalise to just LF
...@@ -165,6 +191,8 @@ private: ...@@ -165,6 +191,8 @@ private:
InteractionType m_interactMode; InteractionType m_interactMode;
ExecutionMode m_execMode; ExecutionMode m_execMode;
ScriptThread *m_execThread;
}; };
......
...@@ -498,11 +498,3 @@ bool muParserScript::executeImpl() ...@@ -498,11 +498,3 @@ bool muParserScript::executeImpl()
} }
return true; return true;
} }
/**
* Execute the script in a seprate thread
*/
QFuture<bool> muParserScript::executeAsyncImpl()
{
throw std::runtime_error("muParser does not support asynchronous execution");
}
...@@ -55,7 +55,6 @@ class muParserScript: public Script ...@@ -55,7 +55,6 @@ class muParserScript: public Script
QString evalSingleLineToString(const QLocale& locale, char f, int prec); QString evalSingleLineToString(const QLocale& locale, char f, int prec);
bool compileImpl(); bool compileImpl();
bool executeImpl(); bool executeImpl();
QFuture<bool> executeAsyncImpl();
bool setQObject(QObject *val, const char *name); bool setQObject(QObject *val, const char *name);
bool setInt(int val, const char* name); bool setInt(int val, const char* name);
bool setDouble(double val, const char* name); bool setDouble(double val, const char* name);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment