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
573 QMetaObject::invokeMethod(this, "registerValue",573 QMetaObject::invokeMethod(this, "registerValue",
574 Q_ARG(const QString&, valueName),574 Q_ARG(const QString&, valueName),
575 Q_ARG(QScriptValue, value));575 Q_ARG(QScriptValue, value));
576 _hasInvokeMethod.wakeAll();
577 return;576 return;
578 }577 }
579 578
@@ -604,7 +603,6 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { · 24 unmodified lines
604 QMetaObject::invokeMethod(this, "registerGlobalObject",603 QMetaObject::invokeMethod(this, "registerGlobalObject",
605 Q_ARG(const QString&, name),604 Q_ARG(const QString&, name),
606 Q_ARG(QObject*, object));605 Q_ARG(QObject*, object));
607 _hasInvokeMethod.wakeAll();
608 return;606 return;
609 }607 }
610#ifdef THREAD_DEBUGGING608#ifdef THREAD_DEBUGGING
@@ -630,7 +628,6 @@ void ScriptEngine::registerFunction(const QString& name, QScriptEngine::Function · 19 unmodified lines
630 Q_ARG(const QString&, name),628 Q_ARG(const QString&, name),
631 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),629 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
632 Q_ARG(int, numArguments));630 Q_ARG(int, numArguments));
633 _hasInvokeMethod.wakeAll();
634 return;631 return;
635 }632 }
636#ifdef THREAD_DEBUGGING633#ifdef THREAD_DEBUGGING
@@ -650,7 +647,6 @@ void ScriptEngine::registerFunction(const QString& parent, const QString& name, · 13 unmodified lines
650 Q_ARG(const QString&, name),647 Q_ARG(const QString&, name),
651 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),648 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
652 Q_ARG(int, numArguments));649 Q_ARG(int, numArguments));
653 _hasInvokeMethod.wakeAll();
654 return;650 return;
655 }651 }
656#ifdef THREAD_DEBUGGING652#ifdef THREAD_DEBUGGING
@@ -676,7 +672,6 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 19 unmodified lines
676 Q_ARG(QScriptEngine::FunctionSignature, getter),672 Q_ARG(QScriptEngine::FunctionSignature, getter),
677 Q_ARG(QScriptEngine::FunctionSignature, setter),673 Q_ARG(QScriptEngine::FunctionSignature, setter),
678 Q_ARG(const QString&, parent));674 Q_ARG(const QString&, parent));
679 _hasInvokeMethod.wakeAll();
680 return;675 return;
681 }676 }
682#ifdef THREAD_DEBUGGING677#ifdef THREAD_DEBUGGING
@@ -709,7 +704,6 @@ void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QStrin · 26 unmodified lines
709 Q_ARG(const EntityItemID&, entityID),704 Q_ARG(const EntityItemID&, entityID),
710 Q_ARG(const QString&, eventName),705 Q_ARG(const QString&, eventName),
711 Q_ARG(QScriptValue, handler));706 Q_ARG(QScriptValue, handler));
712 _hasInvokeMethod.wakeAll();
713 return;707 return;
714 }708 }
715#ifdef THREAD_DEBUGGING709#ifdef THREAD_DEBUGGING
@@ -741,7 +735,6 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 25 unmodified lines
741 Q_ARG(const EntityItemID&, entityID),735 Q_ARG(const EntityItemID&, entityID),
742 Q_ARG(const QString&, eventName),736 Q_ARG(const QString&, eventName),
743 Q_ARG(QScriptValue, handler));737 Q_ARG(QScriptValue, handler));
744 _hasInvokeMethod.wakeAll();
745 return;738 return;
746 }739 }
747#ifdef THREAD_DEBUGGING740#ifdef THREAD_DEBUGGING
@@ -828,7 +821,6 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi · 80 unmodified lines
828 Q_ARG(const QString&, sourceCode),821 Q_ARG(const QString&, sourceCode),
829 Q_ARG(const QString&, fileName),822 Q_ARG(const QString&, fileName),
830 Q_ARG(int, lineNumber));823 Q_ARG(int, lineNumber));
831 _hasInvokeMethod.wakeAll();
832 return result;824 return result;
833 }825 }
834 826
@@ -916,38 +908,11 @@ void ScriptEngine::run() { · 81 unmodified lines
916 break;908 break;
917 }909 }
918 910
919 // determine how long before the next timer should fire, we'd ideally like to sleep just911 // We only want to sleep a small amount so that any pending events (like timers or invokeMethod events)
920 // that long, so the next processEvents() will allow the timers to fire on time.912 // will be able to process quickly.
921 const std::chrono::microseconds minTimerTimeRemaining(USECS_PER_MSEC * getTimersRemainingTime());913 static const int SMALL_SLEEP_AMOUNT = 100;
922 914 auto smallSleepUntil = clock::now() + static_cast<std::chrono::microseconds>(SMALL_SLEEP_AMOUNT);
923 // However, if we haven't yet slept at least as long as our average timer per frame, then we will 915 std::this_thread::sleep_until(smallSleepUntil);
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 }
951 }916 }
952 917
953#ifdef SCRIPT_DELAY_DEBUG918#ifdef SCRIPT_DELAY_DEBUG
@@ -1037,21 +1002,6 @@ void ScriptEngine::run() { · 83 unmodified lines
1037 emit doneRunning();1002 emit doneRunning();
1038}1003}
1039 1004
1040quint64 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
1055// NOTE: This is private because it must be called on the same thread that created the timers, which is why1005// NOTE: This is private because it must be called on the same thread that created the timers, which is why
1056// we want to only call it in our own run "shutdown" processing.1006// we want to only call it in our own run "shutdown" processing.
1057void ScriptEngine::stopAllTimers() {1007void ScriptEngine::stopAllTimers() {
@@ -1062,6 +1012,7 @@ void ScriptEngine::stopAllTimers() { · 4 unmodified lines
1062 stopTimer(timer);1012 stopTimer(timer);
1063 }1013 }
1064}1014}
1015
1065void ScriptEngine::stopAllTimersForEntityScript(const EntityItemID& entityID) {1016void ScriptEngine::stopAllTimersForEntityScript(const EntityItemID& entityID) {
1066 // We could maintain a separate map of entityID => QTimer, but someone will have to prove to me that it's worth the complexity. -HRS1017 // We could maintain a separate map of entityID => QTimer, but someone will have to prove to me that it's worth the complexity. -HRS
1067 QVector<QTimer*> toDelete;1018 QVector<QTimer*> toDelete;
@@ -1085,7 +1036,6 @@ void ScriptEngine::stop(bool marshal) { · 17 unmodified lines
1085 1036
1086 if (marshal) {1037 if (marshal) {
1087 QMetaObject::invokeMethod(this, "stop");1038 QMetaObject::invokeMethod(this, "stop");
1088 _hasInvokeMethod.wakeAll();
1089 return;1039 return;
1090 }1040 }
1091 if (!_isFinished) {1041 if (!_isFinished) {
@@ -1106,7 +1056,6 @@ void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantM · 14 unmodified lines
1106 Q_ARG(QStringList, names),1056 Q_ARG(QStringList, names),
1107 Q_ARG(bool, useNames),1057 Q_ARG(bool, useNames),
1108 Q_ARG(AnimVariantResultHandler, resultHandler));1058 Q_ARG(AnimVariantResultHandler, resultHandler));
1109 _hasInvokeMethod.wakeAll();
1110 return;1059 return;
1111 }1060 }
1112 QScriptValue javascriptParameters = parameters.animVariantMapToScriptValue(this, names, useNames);1061 QScriptValue javascriptParameters = parameters.animVariantMapToScriptValue(this, names, useNames);
@@ -1457,7 +1406,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 344 unmodified lines
1457 Q_ARG(const QString&, contents),1406 Q_ARG(const QString&, contents),
1458 Q_ARG(bool, isURL),1407 Q_ARG(bool, isURL),
1459 Q_ARG(bool, success));1408 Q_ARG(bool, success));
1460 _hasInvokeMethod.wakeAll();
1461 return;1409 return;
1462 }1410 }
1463 1411
@@ -1556,7 +1504,6 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { · 92 unmodified lines
1556 1504
1557 QMetaObject::invokeMethod(this, "unloadEntityScript",1505 QMetaObject::invokeMethod(this, "unloadEntityScript",
1558 Q_ARG(const EntityItemID&, entityID));1506 Q_ARG(const EntityItemID&, entityID));
1559 _hasInvokeMethod.wakeAll();
1560 return;1507 return;
1561 }1508 }
1562#ifdef THREAD_DEBUGGING1509#ifdef THREAD_DEBUGGING
@@ -1578,7 +1525,6 @@ void ScriptEngine::unloadAllEntityScripts() { · 15 unmodified lines
1578#endif1525#endif
1579 1526
1580 QMetaObject::invokeMethod(this, "unloadAllEntityScripts");1527 QMetaObject::invokeMethod(this, "unloadAllEntityScripts");
1581 _hasInvokeMethod.wakeAll();
1582 return;1528 return;
1583 }1529 }
1584#ifdef THREAD_DEBUGGING1530#ifdef THREAD_DEBUGGING
@@ -1665,21 +1611,16 @@ void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl& · 80 unmodified lines
1665}1611}
1666 1612
1667void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) {1613void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) {
1668 qDebug() << "[" << getFilename() << "]" << __FUNCTION__ << "method:" << methodName << "now:" << usecTimestampNow();
1669
1670 if (QThread::currentThread() != thread()) {1614 if (QThread::currentThread() != thread()) {
1671#ifdef THREAD_DEBUGGING1615#ifdef THREAD_DEBUGGING
1672 qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "1616 qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
1673 "entityID:" << entityID << "methodName:" << methodName;1617 "entityID:" << entityID << "methodName:" << methodName;
1674#endif1618#endif
1675 1619
1676 qDebug() << "[" << getFilename() << "]" << "about to invokeMethod callEntityScriptMethod() now:" << usecTimestampNow();
1677
1678 QMetaObject::invokeMethod(this, "callEntityScriptMethod",1620 QMetaObject::invokeMethod(this, "callEntityScriptMethod",
1679 Q_ARG(const EntityItemID&, entityID),1621 Q_ARG(const EntityItemID&, entityID),
1680 Q_ARG(const QString&, methodName),1622 Q_ARG(const QString&, methodName),
1681 Q_ARG(const QStringList&, params));1623 Q_ARG(const QStringList&, params));
1682 _hasInvokeMethod.wakeAll();
1683 return;1624 return;
1684 }1625 }
1685#ifdef THREAD_DEBUGGING1626#ifdef THREAD_DEBUGGING
@@ -1695,8 +1636,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 9 unmodified lines
1695 QScriptValueList args;1636 QScriptValueList args;
1696 args << entityID.toScriptValue(this);1637 args << entityID.toScriptValue(this);
1697 args << qScriptValueFromSequence(this, params);1638 args << qScriptValueFromSequence(this, params);
1698
1699 qDebug() << "[" << getFilename() << "]" << __FUNCTION__ << "about to callWithEnvironment()... method:" << methodName << "now:" << usecTimestampNow();
1700 callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args);1639 callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args);
1701 }1640 }
1702 1641
@@ -1714,7 +1653,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 11 unmodified lines
1714 Q_ARG(const EntityItemID&, entityID),1653 Q_ARG(const EntityItemID&, entityID),
1715 Q_ARG(const QString&, methodName),1654 Q_ARG(const QString&, methodName),
1716 Q_ARG(const PointerEvent&, event));1655 Q_ARG(const PointerEvent&, event));
1717 _hasInvokeMethod.wakeAll();
1718 return;1656 return;
1719 }1657 }
1720#ifdef THREAD_DEBUGGING1658#ifdef THREAD_DEBUGGING
@@ -1748,7 +1686,6 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 27 unmodified lines
1748 Q_ARG(const QString&, methodName),1686 Q_ARG(const QString&, methodName),
1749 Q_ARG(const EntityItemID&, otherID),1687 Q_ARG(const EntityItemID&, otherID),
1750 Q_ARG(const Collision&, collision));1688 Q_ARG(const Collision&, collision));
1751 _hasInvokeMethod.wakeAll();
1752 return;1689 return;
1753 }1690 }
1754#ifdef THREAD_DEBUGGING1691#ifdef THREAD_DEBUGGING