History

Use int handles for script timers instead of QTimer*

Ada committed 8 months ago

Commit 461e32f1 parent db38db73 files · +72 −83Browse files

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

Unified · Split

libraries/script-engine/src/ScriptManager.cpp+53−41
@@ -1171,32 +1171,37 @@ void ScriptManager::run() { · 1170 unmodified lines
11711171 // NOTE: This is private because it must be called on the same thread that created the timers, which is why
11721172 // we want to only call it in our own run "shutdown" processing.
11731173 void ScriptManager::stopAllTimers() {
1174− QMutableHashIterator<QTimer*, CallbackData> i(_timerFunctionMap);
1175− int j {0};
1176− while (i.hasNext()) {
1177− i.next();
1178− QTimer* timer = i.key();
1179− qCDebug(scriptengine) << getFilename() << "stopAllTimers[" << j++ << "]";
1180− stopTimer(timer);
1174+ for (const auto& [handle, value] : _timerFunctionMap) {
1175+ QTimer* timer = std::get<0>(value);
1176+
1177+ timer->stop();
1178+ delete timer;
11811179 }
1180+
1181+ _timerFunctionMap.clear();
1182+ _timerHandleCounter = 1;
11821183 }
11831184
11841185 void ScriptManager::stopAllTimersForEntityScript(const EntityItemID& entityID) {
1185− // We could maintain a separate map of entityID => QTimer, but someone will have to prove to me that it's worth the complexity. -HRS
1186− QVector<QTimer*> toDelete;
1187− QMutableHashIterator<QTimer*, CallbackData> i(_timerFunctionMap);
1188− while (i.hasNext()) {
1189− i.next();
1190− if (i.value().definingEntityIdentifier != entityID) {
1191− continue;
1192− }
1193− QTimer* timer = i.key();
1194− toDelete << timer; // don't delete while we're iterating. save it.
1186+ std::vector<int> toDelete;
1187+
1188+ for (const auto& [handle, value] : _timerFunctionMap) {
1189+ const auto& [timer, callbackData] = value;
1190+
1191+ if (callbackData.definingEntityIdentifier != entityID) { continue; }
1192+
1193+ timer->stop();
1194+ delete timer;
1195+
1196+ toDelete.push_back(handle);
11951197 }
1196− for (auto timer:toDelete) { // now reap 'em
1197− stopTimer(timer);
1198+
1199+ for (auto handle : toDelete) {
1200+ _timerFunctionMap.erase(handle);
11981201 }
11991202
1203+ // the timer map is potentially shared across multiple entity scripts,
1204+ // so don't clear it or reset the handle counter
12001205 }
12011206
12021207 void ScriptManager::stop(bool marshal) {
@@ -1220,7 +1225,7 @@ void ScriptManager::updateMemoryCost(const qint64& deltaSize) { · 17 unmodified lines
12201225 _engine->updateMemoryCost(deltaSize);
12211226 }
12221227
1223−void ScriptManager::timerFired() {
1228+void ScriptManager::timerFired(int handle) {
12241229 if (isStopped()) {
12251230 scriptWarningMessage("Script.timerFired() while shutting down is ignored... parent script:" + getFilename(), getFilename(), -1);
12261231 return; // bail early
@@ -1242,25 +1247,29 @@ void ScriptManager::timerFired() { · 15 unmodified lines
12421247 callTimer.start();
12431248 #endif
12441249
1245− QTimer* callingTimer = reinterpret_cast<QTimer*>(sender());
1246− CallbackData timerData = _timerFunctionMap.value(callingTimer);
1250+ if (!_timerFunctionMap.contains(handle)) {
1251+ qCWarning(scriptengine) << "timerFired -- not in _timerFunctionMap" << handle;
1252+ return;
1253+ }
12471254
1248− if (!callingTimer->isActive()) {
1255+ auto [timer, data] = _timerFunctionMap.at(handle);
1256+
1257+ if (!timer->isActive()) {
12491258 // this timer is done, we can kill it
1250− _timerFunctionMap.remove(callingTimer);
1251− delete callingTimer;
1259+ _timerFunctionMap.erase(handle);
1260+ delete timer;
12521261 }
12531262
12541263 // call the associated JS function, if it exists
1255− if (timerData.function.isValid()) {
1264+ if (data.function.isValid()) {
12561265 PROFILE_RANGE(script, __FUNCTION__);
12571266 auto preTimer = p_high_resolution_clock::now();
1258− callWithEnvironment(timerData.definingEntityIdentifier, timerData.definingSandboxURL, timerData.function, timerData.function, ScriptValueList());
1267+ callWithEnvironment(data.definingEntityIdentifier, data.definingSandboxURL, data.function, data.function, ScriptValueList());
12591268 auto postTimer = p_high_resolution_clock::now();
12601269 auto elapsed = (postTimer - preTimer);
12611270 _totalTimerExecution += std::chrono::duration_cast<std::chrono::microseconds>(elapsed);
12621271 } else {
1263− qCWarning(scriptengine) << "timerFired -- invalid function" << timerData.function.toVariant().toString();
1272+ qCWarning(scriptengine) << "timerFired -- invalid function" << data.function.toVariant().toString();
12641273 }
12651274
12661275 #ifdef SCRIPT_TIMER_PERFORMANCE_STATISTICS
@@ -1268,7 +1277,10 @@ void ScriptManager::timerFired() { · 1 unmodified line
12681277 #endif
12691278 }
12701279
1271−QTimer* ScriptManager::setupTimerWithInterval(const ScriptValue& function, int intervalMS, bool isSingleShot) {
1280+int ScriptManager::setupTimerWithInterval(const ScriptValue& function, int intervalMS, bool isSingleShot) {
1281+ int handle = _timerHandleCounter;
1282+ _timerHandleCounter += 1;
1283+
12721284 // create the timer, add it to the map, and start it
12731285 QTimer* newTimer = new QTimer(this);
12741286 newTimer->setSingleShot(isSingleShot);
@@ -1279,14 +1291,13 @@ QTimer* ScriptManager::setupTimerWithInterval(const ScriptValue& function, int i · 4 unmodified lines
12791291 newTimer->setTimerType(Qt::PreciseTimer);
12801292 }
12811293
1282− connect(newTimer, &QTimer::timeout, this, &ScriptManager::timerFired);
1294+ connect(newTimer, &QTimer::timeout, [this, handle]() { timerFired(handle); });
12831295
12841296 // make sure the timer stops when the script does
12851297 connect(this, &ScriptManager::scriptEnding, newTimer, &QTimer::stop);
12861298
1287−
12881299 CallbackData timerData = { function, currentEntityIdentifier, currentSandboxURL };
1289− _timerFunctionMap.insert(newTimer, timerData);
1300+ _timerFunctionMap.insert({ handle, { newTimer, timerData } });
12901301
12911302 if (intervalMS < 0) {
12921303 int lineNumber = -1;
@@ -1302,10 +1313,10 @@ QTimer* ScriptManager::setupTimerWithInterval(const ScriptValue& function, int i · 9 unmodified lines
13021313 newTimer->start(intervalMS);
13031314 }
13041315
1305− return newTimer;
1316+ return handle;
13061317 }
13071318
1308−QTimer* ScriptManager::setInterval(const ScriptValue& function, int intervalMS) {
1319+int ScriptManager::setInterval(const ScriptValue& function, int intervalMS) {
13091320 if (isStopped()) {
13101321 int lineNumber = -1;
13111322 QString fileName = getFilename();
@@ -1315,13 +1326,13 @@ QTimer* ScriptManager::setInterval(const ScriptValue& function, int intervalMS) · 3 unmodified lines
13151326 fileName = context->currentFileName();
13161327 }
13171328 scriptWarningMessage("Script.setInterval() while shutting down is ignored... parent script:" + getFilename(), fileName, lineNumber);
1318− return NULL; // bail early
1329+ return 0; // bail early
13191330 }
13201331
13211332 return setupTimerWithInterval(function, intervalMS, false);
13221333 }
13231334
1324−QTimer* ScriptManager::setTimeout(const ScriptValue& function, int timeoutMS) {
1335+int ScriptManager::setTimeout(const ScriptValue& function, int timeoutMS) {
13251336 if (isStopped()) {
13261337 int lineNumber = -1;
13271338 QString fileName = getFilename();
@@ -1331,19 +1342,20 @@ QTimer* ScriptManager::setTimeout(const ScriptValue& function, int timeoutMS) { · 3 unmodified lines
13311342 fileName = context->currentFileName();
13321343 }
13331344 scriptWarningMessage("Script.setTimeout() while shutting down is ignored... parent script:" + getFilename(), fileName, lineNumber);
1334− return NULL; // bail early
1345+ return 0; // bail early
13351346 }
13361347
13371348 return setupTimerWithInterval(function, timeoutMS, true);
13381349 }
13391350
1340−void ScriptManager::stopTimer(QTimer *timer) {
1341− if (_timerFunctionMap.contains(timer)) {
1351+void ScriptManager::stopTimer(int handle) {
1352+ if (_timerFunctionMap.contains(handle)) {
1353+ auto [timer, callbackData] = _timerFunctionMap.at(handle);
13421354 timer->stop();
1343− _timerFunctionMap.remove(timer);
1355+ _timerFunctionMap.erase(handle);
13441356 delete timer;
13451357 } else {
1346− qCDebug(scriptengine) << "stopTimer -- not in _timerFunctionMap" << timer;
1358+ qCDebug(scriptengine) << "stopTimer -- not in _timerFunctionMap" << handle;
13471359 }
13481360 }
13491361