From b7b578bf3e39c8a87602947985a8553c0f90ac8a Mon Sep 17 00:00:00 2001 From: rgnter Date: Sun, 18 Dec 2022 14:45:33 +0100 Subject: [PATCH] add conditional variable to LuaResult --- include/TLuaEngine.h | 13 ++++++++++--- src/TConsole.cpp | 4 +--- src/TLuaEngine.cpp | 26 ++++++++++++++++++-------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 21db6d2..c999df5 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -41,7 +41,14 @@ struct TLuaResult { sol::object Result { sol::lua_nil }; TLuaStateId StateId; std::string Function; - // TODO: Add condition_variable + std::shared_ptr ReadyMutex { + std::make_shared() + }; + std::shared_ptr ReadyCondition { + std::make_shared() + }; + + void MarkAsReady(); void WaitUntilReady(); }; @@ -98,8 +105,8 @@ public: return mLuaStates.size(); } std::vector GetLuaStateNames() { - std::vector names{}; - for(auto const& [stateId, _ ] : mLuaStates) { + std::vector names {}; + for (auto const& [stateId, _] : mLuaStates) { names.push_back(stateId); } return names; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 5323288..be57497 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -606,9 +606,7 @@ TConsole::TConsole() { HandleLuaInternalCommand(cmd.substr(1)); } else { auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared(TrimmedCmd), "", "" }); - while (!Future->Ready) { - std::this_thread::yield(); // TODO: Add a timeout - } + Future->WaitUntilReady(); if (Future->Error) { beammp_lua_error("error in " + mStateId + ": " + Future->ErrorMessage); } diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 87f13fa..9d303fe 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -286,6 +286,7 @@ void TLuaEngine::WaitForAll(std::vector>& Results, c bool Cancelled = false; size_t ms = 0; std::set WarnedResults; + while (!Result->Ready && !Cancelled) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); ms += 10; @@ -300,6 +301,7 @@ void TLuaEngine::WaitForAll(std::vector>& Results, c } } } + if (Cancelled) { beammp_lua_warn("'" + Result->Function + "' in '" + Result->StateId + "' failed to execute in time and was not waited for. It may still finish executing at a later time."); LuaAPI::MP::Engine->ReportErrors({ Result }); @@ -425,7 +427,7 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string Result->Error = true; Result->ErrorMessage = "Function result in TriggerGlobalEvent was invalid"; } - Result->Ready = true; + Result->MarkAsReady(); Return.push_back(Result); } } @@ -955,7 +957,7 @@ void TLuaEngine::StateThreadData::operator()() { sol::error Err = Res; S.second->ErrorMessage = Err.what(); } - S.second->Ready = true; + S.second->MarkAsReady(); } } { // StateFunctionQueue Scope @@ -1016,11 +1018,11 @@ void TLuaEngine::StateThreadData::operator()() { sol::error Err = Res; Result->ErrorMessage = Err.what(); } - Result->Ready = true; + Result->MarkAsReady(); } else { Result->Error = true; Result->ErrorMessage = BeamMPFnNotFoundError; // special error kind that we can ignore later - Result->Ready = true; + Result->MarkAsReady(); } } } @@ -1070,11 +1072,19 @@ void TLuaEngine::StateThreadData::AddPath(const fs::path& Path) { mPaths.push(Path); } -void TLuaResult::WaitUntilReady() { - while (!Ready) { - std::this_thread::yield(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); +void TLuaResult::MarkAsReady() { + { + std::lock_guard readyLock(*this->ReadyMutex); + this->Ready = true; } + this->ReadyCondition->notify_all(); +} + +void TLuaResult::WaitUntilReady() { + std::unique_lock readyLock(*this->ReadyMutex); + // wait if not ready yet + if(!this->Ready) + this->ReadyCondition->wait(readyLock); } TLuaChunk::TLuaChunk(std::shared_ptr Content, std::string FileName, std::string PluginPath)