History

make sure RPC is timely

Brad Hefta-Gaub committed 9 years ago

Commit d4405321 parent 82ab8636 files · +387 −81Browse files

Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 6 files). Show all

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+6−69
@@ -573,7 +573,6 @@ void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { · 572 unmodified lines
573573 QMetaObject::invokeMethod(this, "registerValue",
574574 Q_ARG(const QString&, valueName),
575575 Q_ARG(QScriptValue, value));
576− _hasInvokeMethod.wakeAll();
577576 return;
578577 }
579578
@@ -604,7 +603,6 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { · 24 unmodified lines
604603 QMetaObject::invokeMethod(this, "registerGlobalObject",
605604 Q_ARG(const QString&, name),
606605 Q_ARG(QObject*, object));
607− _hasInvokeMethod.wakeAll();
608606 return;
609607 }
610608 #ifdef THREAD_DEBUGGING
@@ -630,7 +628,6 @@ void ScriptEngine::registerFunction(const QString& name, QScriptEngine::Function · 19 unmodified lines
630628 Q_ARG(const QString&, name),
631629 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
632630 Q_ARG(int, numArguments));
633− _hasInvokeMethod.wakeAll();
634631 return;
635632 }
636633 #ifdef THREAD_DEBUGGING
@@ -650,7 +647,6 @@ void ScriptEngine::registerFunction(const QString& parent, const QString& name, · 13 unmodified lines
650647 Q_ARG(const QString&, name),
651648 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
652649 Q_ARG(int, numArguments));
653− _hasInvokeMethod.wakeAll();
654650 return;
655651 }
656652 #ifdef THREAD_DEBUGGING
@@ -676,7 +672,6 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 19 unmodified lines
676672 Q_ARG(QScriptEngine::FunctionSignature, getter),
677673 Q_ARG(QScriptEngine::FunctionSignature, setter),
678674 Q_ARG(const QString&, parent));
679− _hasInvokeMethod.wakeAll();
680675 return;
681676 }
682677 #ifdef THREAD_DEBUGGING
@@ -709,7 +704,6 @@ void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QStrin · 26 unmodified lines
709704 Q_ARG(const EntityItemID&, entityID),
710705 Q_ARG(const QString&, eventName),
711706 Q_ARG(QScriptValue, handler));
712− _hasInvokeMethod.wakeAll();
713707 return;
714708 }
715709 #ifdef THREAD_DEBUGGING
@@ -741,7 +735,6 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 25 unmodified lines
741735 Q_ARG(const EntityItemID&, entityID),
742736 Q_ARG(const QString&, eventName),
743737 Q_ARG(QScriptValue, handler));
744− _hasInvokeMethod.wakeAll();
745738 return;
746739 }
747740 #ifdef THREAD_DEBUGGING
@@ -828,7 +821,6 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi · 80 unmodified lines
828821 Q_ARG(const QString&, sourceCode),
829822 Q_ARG(const QString&, fileName),
830823 Q_ARG(int, lineNumber));
831− _hasInvokeMethod.wakeAll();
832824 return result;
833825 }
834826
@@ -916,38 +908,11 @@ void ScriptEngine::run() { · 81 unmodified lines
916908 break;
917909 }
918910
919− // determine how long before the next timer should fire, we'd ideally like to sleep just
920− // that long, so the next processEvents() will allow the timers to fire on time.
921− const std::chrono::microseconds minTimerTimeRemaining(USECS_PER_MSEC * getTimersRemainingTime());
922−
923− // However, if we haven't yet slept at least as long as our average timer per frame, then we will
924− // punish the timers to at least wait as long as the average run time of the timers.
925− auto untilTimer = std::max(minTimerTimeRemaining, averageTimerPerFrame);
926−
927− // choose the closest time point, our
928− auto remainingSleepUntil = std::chrono::duration_cast<std::chrono::microseconds>(sleepUntil - clock::now());
929− auto closestUntil = std::min(remainingSleepUntil, untilTimer);
930− auto thisSleepUntil = std::min(sleepUntil, clock::now() + closestUntil);
931− auto untilThisSleepUntil = std::chrono::duration_cast<std::chrono::microseconds>(thisSleepUntil - clock::now());
932−
933− // if the sleep until is more than 1 ms away, then don't sleep, and instead use a wait condition
934− // for any possible invoke methods that might also be pending.
935− const std::chrono::microseconds MAX_USECS_TO_SLEEP(USECS_PER_MSEC);
936− if (untilThisSleepUntil < MAX_USECS_TO_SLEEP) {
937− qDebug() << "[" << getFilename() << "]" << "about to sleep untilThisSleepUntil:" << untilThisSleepUntil.count() << "usec -- averageTimerPerFrame:" << averageTimerPerFrame.count();
938− std::this_thread::sleep_until(thisSleepUntil);
939− } else {
940− // FIXME - we might want to make this 1 less ms to wait
941− unsigned long maxWait = untilThisSleepUntil.count() / USECS_PER_MSEC;
942− qDebug() << "[" << getFilename() << "]" << "about to wait:" << maxWait << "ms --- untilThisSleepUntil:" << untilThisSleepUntil.count() << "usec -- averageTimerPerFrame:" << averageTimerPerFrame.count();
943− _waitingOnInvokeMethod.lock();
944− bool signalled = _hasInvokeMethod.wait(&_waitingOnInvokeMethod, maxWait);
945− _waitingOnInvokeMethod.unlock();
946− if (signalled) {
947− qDebug() << "[" << getFilename() << "]" << "SIGNALLED!! done waiting... now:" << usecTimestampNow();
948− }
949−
950− }
911+ // We only want to sleep a small amount so that any pending events (like timers or invokeMethod events)
912+ // will be able to process quickly.
913+ static const int SMALL_SLEEP_AMOUNT = 100;
914+ auto smallSleepUntil = clock::now() + static_cast<std::chrono::microseconds>(SMALL_SLEEP_AMOUNT);
915+ std::this_thread::sleep_until(smallSleepUntil);
951916 }
952917
953918 #ifdef SCRIPT_DELAY_DEBUG
@@ -1037,21 +1002,6 @@ void ScriptEngine::run() { · 83 unmodified lines
10371002 emit doneRunning();
10381003 }
10391004
1040−quint64 ScriptEngine::getTimersRemainingTime() {
1041− quint64 minimumTime = USECS_PER_SECOND; // anything larger than this can be ignored
1042− QMutableHashIterator<QTimer*, CallbackData> i(_timerFunctionMap);
1043− while (i.hasNext()) {
1044− i.next();
1045− QTimer* timer = i.key();
1046− int remainingTime = timer->remainingTime();
1047− if (remainingTime >= 0) {
1048− minimumTime = std::min((quint64)remainingTime, minimumTime);
1049− }
1050− }
1051− return minimumTime;
1052−}
1053−
1054−
10551005 // NOTE: This is private because it must be called on the same thread that created the timers, which is why
10561006 // we want to only call it in our own run "shutdown" processing.
10571007 void ScriptEngine::stopAllTimers() {
@@ -1062,6 +1012,7 @@ void ScriptEngine::stopAllTimers() { · 4 unmodified lines
10621012 stopTimer(timer);
10631013 }
10641014 }
1015+
10651016 void ScriptEngine::stopAllTimersForEntityScript(const EntityItemID& entityID) {
10661017 // We could maintain a separate map of entityID => QTimer, but someone will have to prove to me that it's worth the complexity. -HRS
10671018 QVector<QTimer*> toDelete;
@@ -1085,7 +1036,6 @@ void ScriptEngine::stop(bool marshal) { · 17 unmodified lines
10851036
10861037 if (marshal) {
10871038 QMetaObject::invokeMethod(this, "stop");
1088− _hasInvokeMethod.wakeAll();
10891039 return;
10901040 }
10911041 if (!_isFinished) {
@@ -1106,7 +1056,6 @@ void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantM · 14 unmodified lines
11061056 Q_ARG(QStringList, names),
11071057 Q_ARG(bool, useNames),
11081058 Q_ARG(AnimVariantResultHandler, resultHandler));
1109− _hasInvokeMethod.wakeAll();
11101059 return;
11111060 }
11121061 QScriptValue javascriptParameters = parameters.animVariantMapToScriptValue(this, names, useNames);
@@ -1457,7 +1406,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 344 unmodified lines
14571406 Q_ARG(const QString&, contents),
14581407 Q_ARG(bool, isURL),
14591408 Q_ARG(bool, success));
1460− _hasInvokeMethod.wakeAll();
14611409 return;
14621410 }
14631411
@@ -1556,7 +1504,6 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { · 92 unmodified lines
15561504
15571505 QMetaObject::invokeMethod(this, "unloadEntityScript",
15581506 Q_ARG(const EntityItemID&, entityID));
1559− _hasInvokeMethod.wakeAll();
15601507 return;
15611508 }
15621509 #ifdef THREAD_DEBUGGING
@@ -1578,7 +1525,6 @@ void ScriptEngine::unloadAllEntityScripts() { · 15 unmodified lines
15781525 #endif
15791526
15801527 QMetaObject::invokeMethod(this, "unloadAllEntityScripts");
1581− _hasInvokeMethod.wakeAll();
15821528 return;
15831529 }
15841530 #ifdef THREAD_DEBUGGING
@@ -1665,21 +1611,16 @@ void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl& · 80 unmodified lines
16651611 }
16661612
16671613 void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) {
1668− qDebug() << "[" << getFilename() << "]" << __FUNCTION__ << "method:" << methodName << "now:" << usecTimestampNow();
1669−
16701614 if (QThread::currentThread() != thread()) {
16711615 #ifdef THREAD_DEBUGGING
16721616 qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
16731617 "entityID:" << entityID << "methodName:" << methodName;
16741618 #endif
16751619
1676− qDebug() << "[" << getFilename() << "]" << "about to invokeMethod callEntityScriptMethod() now:" << usecTimestampNow();
1677−
16781620 QMetaObject::invokeMethod(this, "callEntityScriptMethod",
16791621 Q_ARG(const EntityItemID&, entityID),
16801622 Q_ARG(const QString&, methodName),
16811623 Q_ARG(const QStringList&, params));
1682− _hasInvokeMethod.wakeAll();
16831624 return;
16841625 }
16851626 #ifdef THREAD_DEBUGGING
@@ -1695,8 +1636,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 9 unmodified lines
16951636 QScriptValueList args;
16961637 args << entityID.toScriptValue(this);
16971638 args << qScriptValueFromSequence(this, params);
1698−
1699− qDebug() << "[" << getFilename() << "]" << __FUNCTION__ << "about to callWithEnvironment()... method:" << methodName << "now:" << usecTimestampNow();
17001639 callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args);
17011640 }
17021641
@@ -1714,7 +1653,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 11 unmodified lines
17141653 Q_ARG(const EntityItemID&, entityID),
17151654 Q_ARG(const QString&, methodName),
17161655 Q_ARG(const PointerEvent&, event));
1717− _hasInvokeMethod.wakeAll();
17181656 return;
17191657 }
17201658 #ifdef THREAD_DEBUGGING
@@ -1748,7 +1686,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 27 unmodified lines
17481686 Q_ARG(const QString&, methodName),
17491687 Q_ARG(const EntityItemID&, otherID),
17501688 Q_ARG(const Collision&, collision));
1751− _hasInvokeMethod.wakeAll();
17521689 return;
17531690 }
17541691 #ifdef THREAD_DEBUGGING