mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
TLuaEngine: improve result queue handling
This commit is contained in:
parent
de82caef33
commit
b97397132d
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user