optimize: Add conditional variable to LuaResult (#162)

Implementing TODO for optimization I saw in the code.
This commit is contained in:
Lion 2023-03-27 13:31:21 +02:00 committed by GitHub
commit 2c29a195f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 14 deletions

View File

@ -41,7 +41,14 @@ struct TLuaResult {
sol::object Result { sol::lua_nil }; sol::object Result { sol::lua_nil };
TLuaStateId StateId; TLuaStateId StateId;
std::string Function; std::string Function;
// TODO: Add condition_variable std::shared_ptr<std::mutex> ReadyMutex {
std::make_shared<std::mutex>()
};
std::shared_ptr<std::condition_variable> ReadyCondition {
std::make_shared<std::condition_variable>()
};
void MarkAsReady();
void WaitUntilReady(); void WaitUntilReady();
}; };
@ -98,8 +105,8 @@ public:
return mLuaStates.size(); return mLuaStates.size();
} }
std::vector<std::string> GetLuaStateNames() { std::vector<std::string> GetLuaStateNames() {
std::vector<std::string> names{}; std::vector<std::string> names {};
for(auto const& [stateId, _ ] : mLuaStates) { for (auto const& [stateId, _] : mLuaStates) {
names.push_back(stateId); names.push_back(stateId);
} }
return names; return names;

View File

@ -606,9 +606,7 @@ TConsole::TConsole() {
HandleLuaInternalCommand(cmd.substr(1)); HandleLuaInternalCommand(cmd.substr(1));
} else { } else {
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(TrimmedCmd), "", "" }); auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(TrimmedCmd), "", "" });
while (!Future->Ready) { Future->WaitUntilReady();
std::this_thread::yield(); // TODO: Add a timeout
}
if (Future->Error) { if (Future->Error) {
beammp_lua_error("error in " + mStateId + ": " + Future->ErrorMessage); beammp_lua_error("error in " + mStateId + ": " + Future->ErrorMessage);
} }

View File

@ -286,6 +286,7 @@ void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, c
bool Cancelled = false; bool Cancelled = false;
size_t ms = 0; size_t ms = 0;
std::set<std::string> WarnedResults; std::set<std::string> WarnedResults;
while (!Result->Ready && !Cancelled) { while (!Result->Ready && !Cancelled) {
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
ms += 10; ms += 10;
@ -300,6 +301,7 @@ void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, c
} }
} }
} }
if (Cancelled) { 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."); 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 }); LuaAPI::MP::Engine->ReportErrors({ Result });
@ -425,7 +427,7 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string
Result->Error = true; Result->Error = true;
Result->ErrorMessage = "Function result in TriggerGlobalEvent was invalid"; Result->ErrorMessage = "Function result in TriggerGlobalEvent was invalid";
} }
Result->Ready = true; Result->MarkAsReady();
Return.push_back(Result); Return.push_back(Result);
} }
} }
@ -955,7 +957,7 @@ void TLuaEngine::StateThreadData::operator()() {
sol::error Err = Res; sol::error Err = Res;
S.second->ErrorMessage = Err.what(); S.second->ErrorMessage = Err.what();
} }
S.second->Ready = true; S.second->MarkAsReady();
} }
} }
{ // StateFunctionQueue Scope { // StateFunctionQueue Scope
@ -1016,11 +1018,11 @@ void TLuaEngine::StateThreadData::operator()() {
sol::error Err = Res; sol::error Err = Res;
Result->ErrorMessage = Err.what(); Result->ErrorMessage = Err.what();
} }
Result->Ready = true; Result->MarkAsReady();
} else { } else {
Result->Error = true; Result->Error = true;
Result->ErrorMessage = BeamMPFnNotFoundError; // special error kind that we can ignore later 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); mPaths.push(Path);
} }
void TLuaResult::WaitUntilReady() { void TLuaResult::MarkAsReady() {
while (!Ready) { {
std::this_thread::yield(); std::lock_guard<std::mutex> readyLock(*this->ReadyMutex);
std::this_thread::sleep_for(std::chrono::milliseconds(10)); 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<std::string> Content, std::string FileName, std::string PluginPath) TLuaChunk::TLuaChunk(std::shared_ptr<std::string> Content, std::string FileName, std::string PluginPath)