36 #include <QCoreApplication> 39 #ifdef ARNUSE_SCRIPTJS 41 #include <QMetaObject> 43 #include <QScriptable> 45 #include <QScriptEngine> 48 const QEvent::Type
EventQuit = QEvent::Type( QEvent::User + 0);
51 ArnScriptJobB::ArnScriptJobB(
int id, QObject* parent) :
55 _isSleepState =
false;
58 _quitInProgress =
false;
62 _jobFactory = arnNullptr;
63 _watchdog = arnNullptr;
64 _configObj =
new QObject(
this);
66 setPollTime( _pollTime);
68 _watchdog =
new ArnScriptWatchdog( &_arnScr->engine(),
this);
70 connect( _watchdog, SIGNAL(timeout()),
this, SLOT(doTimeoutAbort()));
71 connect( _arnScr, SIGNAL(errorText(QString)),
this, SIGNAL(errorText(QString)));
73 #ifdef ARNUSE_SCRIPTJS 74 _arnScr->setInterruptedText(
"Error: Job run timeout");
79 void ArnScriptJobB::setWatchDogTime(
int time)
85 int ArnScriptJobB::watchDogTime()
91 void ArnScriptJobB::setWatchDog(
int time,
bool persist)
100 #ifdef ARNUSE_SCRIPTJS 101 _watchdog->setTime( wt);
103 _watchdog->setTime( wt);
105 _arnScr->engine().setProcessEventsInterval( wt);
108 _arnScr->engine().setProcessEventsInterval( _watchDogTime > 0 ? _watchDogTime : _pollTime);
114 void ArnScriptJobB::setPollTime(
int time)
118 #ifdef ARNUSE_SCRIPTJS 121 _arnScr->engine().setProcessEventsInterval( _pollTime);
126 int ArnScriptJobB::pollTime()
132 void ArnScriptJobB::installInterface(
const QString&
id, QObject* obj)
134 if ((
id.isEmpty()) || (obj == arnNullptr))
return;
136 if (obj !=
this) obj->setParent(
this);
139 _arnScr->addObject(
id, obj);
145 if (!_jobFactory || !_arnScr)
return false;
147 return _jobFactory->installExtension(
id, _arnScr->engine(), jobControl);
151 bool ArnScriptJobB::evaluateScript(
const QByteArray& script,
const QString& idName)
156 QByteArray conf =
"config = {";
159 QList<QByteArray> nameList = _configObj->dynamicPropertyNames();
160 foreach (QByteArray name, nameList) {
162 name.replace(
".",
"_");
163 conf += name +
": \"" + _configObj->property( name.constData()).toString().toUtf8() +
"\"" ;
167 stat = _arnScr->evaluate( conf, idName,
"Config");
169 errorLog(
"Config-script: " + conf );
172 stat = _arnScr->evaluate( script, idName);
174 setWatchDog( 0,
false);
179 bool ArnScriptJobB::evaluateScriptFile(
const QString& fileName)
182 bool stat = _arnScr->evaluateFile( fileName);
183 setWatchDog( 0,
false);
188 int ArnScriptJobB::id()
const 194 QString ArnScriptJobB::name()
const 196 return _arnScr->idName();
200 bool ArnScriptJobB::setConfig(
const char* name,
const QVariant& value)
202 if (!name)
return false;
204 return _configObj->setProperty( name, value);
208 void ArnScriptJobB::addConfig( QObject* obj)
212 QList<QByteArray> nameList = obj->dynamicPropertyNames();
213 foreach (QByteArray name, nameList) {
214 setConfig( name.constData(), obj->property( name.constData()));
221 _jobFactory = jobFactory;
231 ArnScriptWatchdog* ArnScriptJobB::watchdog()
const 237 bool ArnScriptJobB::setupScript()
239 _jobInit = _arnScr->globalProperty(
"jobInit");
240 _jobEnter = _arnScr->globalProperty(
"jobEnter");
241 _jobLeave = _arnScr->globalProperty(
"jobLeave");
245 if (result.isError()) {
249 setWatchDog( 0,
false);
255 void ArnScriptJobB::enterScript()
257 if (isStopped())
return;
262 if (result.isError()) {
263 setWatchDog( 0,
false);
267 emit scheduleRequest( _id);
272 void ArnScriptJobB::leaveScript()
274 if (isStopped())
return;
277 if (result.isError()) {
282 setWatchDog( 0,
false);
286 void ArnScriptJobB::yield()
288 emit scheduleRequest( _id);
292 void ArnScriptJobB::quit()
294 if (_quitInProgress)
return;
295 _quitInProgress =
true;
298 #ifdef ARNUSE_SCRIPTJS 300 engine.setInterrupted(
true);
302 engine.abortEvaluation( engine.currentContext()->throwError(
"Job quit"));
306 QCoreApplication::postEvent(
this, ev, Qt::HighEventPriority);
310 void ArnScriptJobB::customEvent(QEvent *ev)
312 switch (ev->type()) {
314 _quitInProgress =
false;
315 emit quitRequest( _id);
322 void ArnScriptJobB::doTimeoutAbort()
324 #ifdef ARNUSE_SCRIPTJS 328 engine.setInterrupted(
false);
331 errorLog(
"Error: Job run timeout sig");
333 emit scheduleRequest( _id);
339 errorLog(
"Error: Watchdog timeout");
341 engine.abortEvaluation( engine.currentContext()->throwError(
"Job run timeout"));
343 emit scheduleRequest( _id);
346 emit timeoutAbort( _id);
350 void ArnScriptJobB::setSleepState(
bool isSleepState)
352 _isSleepState = isSleepState;
354 emit scheduleRequest( _id);
358 bool ArnScriptJobB::isSleepState()
const 360 return _isSleepState;
364 bool ArnScriptJobB::isRunable()
const 366 return !_isSleepState && !_isStopped;
370 bool ArnScriptJobB::isStopped()
const 376 bool ArnScriptJobB::isRunning()
const 383 void ArnScriptJobB::errorLog(
const QString& txt)
386 emit errorText( txt);
402 engine.globalObject().setProperty(
id, jsObj);
408 if (
id.isEmpty() || (interface == arnNullptr))
return false;
410 #ifdef ARNUSE_SCRIPTJS 411 ARN_JSVALUE objScr = engine.newQObject( interface);
413 QScriptValue objScr = engine.newQObject( interface, QScriptEngine::QtOwnership,
414 QScriptEngine::ExcludeSuperClassContents);
416 if (objScr.isNull())
return false;
420 if (!interface->parent())
421 interface->setParent( engine.parent());
430 ArnScriptWatchdog::ArnScriptWatchdog(
ARN_JSENGINE* jsEngine, QObject* parent)
433 _jsEngine = jsEngine;
436 _timer =
new QTimer(
this);
437 _timer->setSingleShot(
true);
441 ArnScriptWatchdog::~ArnScriptWatchdog()
446 void ArnScriptWatchdog::setup()
448 #ifdef ARNUSE_SCRIPTJS 449 connect( _timer, &QTimer::timeout,
453 _jsEngine->setInterrupted(
true);
458 connect( _timer, SIGNAL(timeout()),
this, SIGNAL(timeout()));
460 setTimeNow( _lastTimeMs );
466 void ArnScriptWatchdog::setJsEngine(
ARN_JSENGINE* jsEngine)
469 _jsEngine = jsEngine;
475 void ArnScriptWatchdog::setTime(
int timeMs)
477 _lastTimeMs = timeMs;
479 #ifdef ARNUSE_SCRIPTJS 480 QMetaObject::invokeMethod(
this, [timeMs,
this]() { this->setTimeNow( timeMs); }, Qt::QueuedConnection);
488 void ArnScriptWatchdog::setTimeNow(
int timeMs)
491 _timer->start( timeMs);
500 ArnScriptJobB( id, parent)
502 installInterface(
"job",
this);
504 installInterface(
"config", _configObj);
509 QAtomicInt ArnScriptJobControl::_idCount(1);
515 _id = _idCount.fetchAndAddRelaxed(1);
516 _configObj =
new QObject(
this);
523 if (_isThreaded) _mutex.lock();
525 if (_isThreaded) _mutex.unlock();
531 if (_isThreaded) _mutex.lock();
533 if (_isThreaded) _mutex.unlock();
541 if (_isThreaded) _mutex.lock();
542 QString retVal = _name;
543 if (_isThreaded) _mutex.unlock();
551 if (_isThreaded) _mutex.lock();
552 if (!
id.isEmpty()) _interfaceList +=
id;
553 _interfaceList.removeDuplicates();
554 if (_isThreaded) _mutex.unlock();
560 if (_isThreaded) _mutex.lock();
561 _interfaceList += interfaceList;
562 _interfaceList.removeDuplicates();
563 if (_isThreaded) _mutex.unlock();
569 if (_isThreaded) _mutex.lock();
571 if (_isThreaded) _mutex.unlock();
579 if (_isThreaded) _mutex.lock();
580 QByteArray retVal = _script;
581 if (_isThreaded) _mutex.unlock();
589 if (fileName.isEmpty())
return;
591 QFile file( fileName);
592 file.open( QIODevice::ReadOnly);
594 setName( QFileInfo( file).baseName());
601 if (!
name)
return false;
603 if (_isThreaded) _mutex.lock();
604 bool retVal = _configObj->setProperty(
name, value);
605 if (_isThreaded) _mutex.unlock();
615 QList<QByteArray> nameList = obj->dynamicPropertyNames();
616 foreach (QByteArray
name, nameList) {
624 _isThreaded = isThreaded;
632 if (!jobFactory)
return;
635 job->setJobFactory( jobFactory);
636 foreach (QString
id, _interfaceList) {
637 job->installExtension(
id,
this);
639 job->addConfig( _configObj);
640 job->evaluateScript( _script, _name);
647 if (!
name)
return QVariant();
649 if (_isThreaded) _mutex.lock();
650 QVariant retVal = _configObj->property(
name);
651 if (_isThreaded) _mutex.unlock();
void setThreaded(bool isThreaded)
ArnScriptJobControl(QObject *parent=arnNullptr)
void addInterfaceList(const QStringList &interfaceList)
static bool setupInterface(const QString &id, QObject *interface, ARN_JSENGINE &engine)
QByteArray script() const
void setName(const QString &name)
bool setConfig(const char *name, const QVariant &value)
static void setupJsObj(const QString &id, const ARN_JSVALUE &jsObj, ARN_JSENGINE &engine)
void scriptChanged(int id)
QVariant config(const char *name) const
Must be thread-safe as subclassed.
Is thread-safe (except doSetupJob)
Interface class to be normally used, is also Script Job interface.
ArnScriptJob(int id, QObject *parent=arnNullptr)
const QEvent::Type EventQuit
void addConfig(QObject *obj)
static void errorLog(QString errText, ArnError err=ArnError::Undef, void *reference=arnNullptr)
void setScript(const QByteArray &script)
void doSetupJob(ArnScriptJob *job, ArnScriptJobFactory *jobFactory)
Not threadsafe, only run in same thread as script.
void loadScriptFile(const QString &fileName)
virtual ~ArnScriptJobFactory()
void addInterface(const QString &id)