Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 6 files). Show all
Unified · Split
| @@ -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_DEBUGGING | 608 | #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_DEBUGGING | 633 | #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_DEBUGGING | 652 | #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_DEBUGGING | 677 | #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_DEBUGGING | 709 | #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_DEBUGGING | 740 | #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 just | 911 | // 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_DEBUG | 918 | #ifdef SCRIPT_DELAY_DEBUG |
| @@ -1037,21 +1002,6 @@ void ScriptEngine::run() { · 83 unmodified lines | |||
| 1037 | emit doneRunning(); | 1002 | emit doneRunning(); |
| 1038 | } | 1003 | } |
| 1039 | 1004 | ||
| 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 | |||
| 1055 | // NOTE: This is private because it must be called on the same thread that created the timers, which is why | 1005 | // 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. |
| 1057 | void ScriptEngine::stopAllTimers() { | 1007 | void ScriptEngine::stopAllTimers() { |
| @@ -1062,6 +1012,7 @@ void ScriptEngine::stopAllTimers() { · 4 unmodified lines | |||
| 1062 | stopTimer(timer); | 1012 | stopTimer(timer); |
| 1063 | } | 1013 | } |
| 1064 | } | 1014 | } |
| 1015 | |||
| 1065 | void ScriptEngine::stopAllTimersForEntityScript(const EntityItemID& entityID) { | 1016 | void 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. -HRS | 1017 | // 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_DEBUGGING | 1509 | #ifdef THREAD_DEBUGGING |
| @@ -1578,7 +1525,6 @@ void ScriptEngine::unloadAllEntityScripts() { · 15 unmodified lines | |||
| 1578 | #endif | 1525 | #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_DEBUGGING | 1530 | #ifdef THREAD_DEBUGGING |
| @@ -1665,21 +1611,16 @@ void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl& · 80 unmodified lines | |||
| 1665 | } | 1611 | } |
| 1666 | 1612 | ||
| 1667 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) { | 1613 | void 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_DEBUGGING | 1615 | #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 | #endif | 1618 | #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_DEBUGGING | 1626 | #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_DEBUGGING | 1658 | #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_DEBUGGING | 1691 | #ifdef THREAD_DEBUGGING |