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)