TLuaEngine: improve result queue handling

This commit is contained in:
Lion Kortlepel 2022-03-31 15:59:31 +02:00
parent de82caef33
commit b97397132d
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
3 changed files with 27 additions and 23 deletions

View File

@ -5,6 +5,7 @@
#include <any> #include <any>
#include <condition_variable> #include <condition_variable>
#include <filesystem> #include <filesystem>
#include <list>
#include <initializer_list> #include <initializer_list>
#include <lua.hpp> #include <lua.hpp>
#include <memory> #include <memory>
@ -218,8 +219,9 @@ private:
std::recursive_mutex mLuaEventsMutex; std::recursive_mutex mLuaEventsMutex;
std::vector<TimedEvent> mTimedEvents; std::vector<TimedEvent> mTimedEvents;
std::recursive_mutex mTimedEventsMutex; std::recursive_mutex mTimedEventsMutex;
std::queue<std::shared_ptr<TLuaResult>> mResultsToCheck; std::list<std::shared_ptr<TLuaResult>> mResultsToCheck;
std::recursive_mutex mResultsToCheckMutex; std::mutex mResultsToCheckMutex;
std::condition_variable mResultsToCheckCond;
}; };
// std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr<TLuaArg> arg, bool Wait); // std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr<TLuaArg> arg, bool Wait);

View File

@ -44,7 +44,7 @@ void TLuaEngine::operator()() {
CollectAndInitPlugins(); CollectAndInitPlugins();
// now call all onInit's // now call all onInit's
auto Futures = TriggerEvent("onInit", ""); auto Futures = TriggerEvent("onInit", "");
WaitForAll(Futures); WaitForAll(Futures, std::chrono::seconds(5));
for (const auto& Future : Futures) { for (const auto& Future : Futures) {
if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) { if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) {
beammp_lua_error("Calling \"onInit\" on \"" + Future->StateId + "\" failed: " + Future->ErrorMessage); beammp_lua_error("Calling \"onInit\" on \"" + Future->StateId + "\" failed: " + Future->ErrorMessage);
@ -54,25 +54,21 @@ void TLuaEngine::operator()() {
auto ResultCheckThread = std::thread([&] { auto ResultCheckThread = std::thread([&] {
RegisterThread("ResultCheckThread"); RegisterThread("ResultCheckThread");
while (!mShutdown) { while (!mShutdown) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::unique_lock Lock(mResultsToCheckMutex); std::unique_lock Lock(mResultsToCheckMutex);
mResultsToCheckCond.wait_for(Lock, std::chrono::milliseconds(20));
if (!mResultsToCheck.empty()) { if (!mResultsToCheck.empty()) {
auto Res = mResultsToCheck.front(); mResultsToCheck.remove_if([](const std::shared_ptr<TLuaResult>& Ptr) -> bool {
mResultsToCheck.pop(); if (Ptr->Ready) {
Lock.unlock(); return true;
} else if (Ptr->Error) {
if (!Res->Ready) { if (Ptr->ErrorMessage != BeamMPFnNotFoundError) {
Lock.lock(); beammp_lua_error(Ptr->Function + ": " + Ptr->ErrorMessage);
mResultsToCheck.push(Res); }
Lock.unlock(); return true;
}
if (Res->Error) {
if (Res->ErrorMessage != BeamMPFnNotFoundError) {
beammp_lua_error(Res->Function + ": " + Res->ErrorMessage);
} }
} return false;
});
} }
std::this_thread::yield();
} }
}); });
// event loop // event loop
@ -91,7 +87,8 @@ void TLuaEngine::operator()() {
std::unique_lock Lock2(mResultsToCheckMutex); std::unique_lock Lock2(mResultsToCheckMutex);
for (auto& Handler : Handlers) { for (auto& Handler : Handlers) {
auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCall(Handler, {}); auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCall(Handler, {});
mResultsToCheck.push(Res); mResultsToCheck.push_back(Res);
mResultsToCheckCond.notify_one();
} }
} }
} }
@ -144,7 +141,8 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
void TLuaEngine::AddResultToCheck(const std::shared_ptr<TLuaResult>& Result) { void TLuaEngine::AddResultToCheck(const std::shared_ptr<TLuaResult>& Result) {
std::unique_lock Lock(mResultsToCheckMutex); std::unique_lock Lock(mResultsToCheckMutex);
mResultsToCheck.push(Result); mResultsToCheck.push_back(Result);
mResultsToCheckCond.notify_one();
} }
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) { void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
@ -155,9 +153,12 @@ void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, c
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
ms += 10; ms += 10;
if (Max.has_value() && std::chrono::milliseconds(ms) > Max.value()) { if (Max.has_value() && std::chrono::milliseconds(ms) > Max.value()) {
beammp_trace("'" + Result->Function + "' in '" + Result->StateId + "' did not finish executing in time (took: " + std::to_string(ms) + "ms)"); beammp_trace("'" + Result->Function + "' in '" + Result->StateId + "' did not finish executing in time (took: " + std::to_string(ms) + "ms).");
Cancelled = true; Cancelled = true;
} }
else if (ms > 1000 * 60) {
beammp_lua_warn("'" + Result->Function +"' in '" + Result->StateId + "' is taking very long. The event it's handling is too important to discard the result of this handler, but may block this event and possibly the whole lua state.");
}
} }
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.");
@ -174,7 +175,8 @@ void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, c
void TLuaEngine::ReportErrors(const std::vector<std::shared_ptr<TLuaResult>>& Results) { void TLuaEngine::ReportErrors(const std::vector<std::shared_ptr<TLuaResult>>& Results) {
std::unique_lock Lock2(mResultsToCheckMutex); std::unique_lock Lock2(mResultsToCheckMutex);
for (const auto& Result : Results) { for (const auto& Result : Results) {
mResultsToCheck.push(Result); mResultsToCheck.push_back(Result);
mResultsToCheckCond.notify_one();
} }
} }

View File

@ -133,7 +133,7 @@ int BeamMPServerMain(MainArguments Arguments) {
}); });
Application::RegisterShutdownHandler([] { Application::RegisterShutdownHandler([] {
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", ""); auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", "");
TLuaEngine::WaitForAll(Futures); TLuaEngine::WaitForAll(Futures, std::chrono::seconds(5));
}); });
TServer Server(Arguments.List); TServer Server(Arguments.List);