Got rid of multithreading in GameMode

This commit is contained in:
2026-02-27 17:49:29 -05:00
parent 7bb4854844
commit 8825fe3a1e
2 changed files with 48 additions and 70 deletions

View File

@@ -19,57 +19,19 @@
using namespace LpxCommonTypes; using namespace LpxCommonTypes;
ALuprexGameModeBase::ALuprexGameModeBase() ALuprexGameModeBase::ALuprexGameModeBase() {}
{ ALuprexGameModeBase::~ALuprexGameModeBase() {}
}
ALuprexGameModeBase::~ALuprexGameModeBase()
{
}
// This method runs in the background thread,
// at the moment we trigger it.
//
uint32 ALuprexGameModeBase::Run() {
FlxLockedWrapper lockedwrap;
if (lockedwrap->get_rescan_lua_source(lockedwrap.Get()))
{
drvutil::ostringstream srcpak;
FString LuprexRoot = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex"));
std::string srcpakerr = drvutil::package_lua_source(TCHAR_TO_UTF8(*LuprexRoot), &srcpak);
if (!srcpakerr.empty())
{
FString FMessage((const UTF8CHAR *)(srcpakerr.c_str()));
UE_LOG(LogLuprexIntegration, Error, TEXT("Trying to read Lua source: %s"), *FMessage);
}
else
{
std::string_view srcpakv = srcpak.view();
lockedwrap->play_access(lockedwrap.Get(), AccessKind::INVOKE_LUA_SOURCE, 0, srcpakv.size(), srcpakv.data(), nullptr, nullptr);
}
}
Sockets->Update(lockedwrap);
lockedwrap->play_update(lockedwrap.Get(), EngineSeconds);
Sockets->Update(lockedwrap);
return 0;
}
void ALuprexGameModeBase::ResetToInitialState() void ALuprexGameModeBase::ResetToInitialState()
{ {
Playing = false; Playing = false;
TickEnabled = true; TickEnabled = true;
// Stop the tick functions. // Stop the tick function.
FWorldDelegates::OnWorldPreActorTick.Remove(OnWorldPreActorTickHandle);
FWorldDelegates::OnWorldPostActorTick.Remove(OnWorldPostActorTickHandle); FWorldDelegates::OnWorldPostActorTick.Remove(OnWorldPostActorTickHandle);
OnWorldPreActorTickHandle.Reset();
OnWorldPostActorTickHandle.Reset(); OnWorldPostActorTickHandle.Reset();
// Shut down the thread
LuprexUpdateTask.Shutdown();
// Now that the thread's gone, we should be able to
// just claim and hold the lock on the wrapper.
FlxLockedWrapper w; FlxLockedWrapper w;
// Release and close all sockets. // Release and close all sockets.
@@ -172,25 +134,45 @@ void ALuprexGameModeBase::UpdatePossessedTangible() {
} }
} }
void ALuprexGameModeBase::UpdateLuaSourceCode() {
void ALuprexGameModeBase::OnWorldPreActorTick(UWorld* InWorld, ELevelTick InLevelTick, float deltaseconds) FlxLockedWrapper lockedwrap;
{ if (lockedwrap->get_rescan_lua_source(lockedwrap.Get()))
if(Playing && TickEnabled && (GetWorld() == InWorld) && (InLevelTick == LEVELTICK_All))
{ {
LuprexUpdateTask.Wait(); drvutil::ostringstream srcpak;
EngineSeconds += deltaseconds; FString LuprexRoot = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex"));
UpdateConsoleOutput(); std::string srcpakerr = drvutil::package_lua_source(TCHAR_TO_UTF8(*LuprexRoot), &srcpak);
UpdateTangibles(); if (!srcpakerr.empty())
UpdatePossessedTangible(); {
UpdateLookAt(); FString FMessage((const UTF8CHAR *)(srcpakerr.c_str()));
UE_LOG(LogLuprexIntegration, Error, TEXT("Trying to read Lua source: %s"), *FMessage);
} }
else
{
std::string_view srcpakv = srcpak.view();
lockedwrap->play_access(lockedwrap.Get(), AccessKind::INVOKE_LUA_SOURCE, 0, srcpakv.size(), srcpakv.data(), nullptr, nullptr);
}
}
}
void ALuprexGameModeBase::UpdateSocketsAndLua()
{
FlxLockedWrapper lockedwrap;
Sockets->Update(lockedwrap);
lockedwrap->play_update(lockedwrap.Get(), EngineSeconds);
Sockets->Update(lockedwrap);
} }
void ALuprexGameModeBase::OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float deltaseconds) void ALuprexGameModeBase::OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float deltaseconds)
{ {
if(Playing && TickEnabled && (GetWorld() == InWorld) && (InLevelTick == LEVELTICK_All)) if(Playing && TickEnabled && (GetWorld() == InWorld) && (InLevelTick == LEVELTICK_All))
{ {
LuprexUpdateTask.Trigger(); EngineSeconds += deltaseconds;
UpdateLuaSourceCode();
UpdateSocketsAndLua();
UpdateConsoleOutput();
UpdateTangibles();
UpdatePossessedTangible();
UpdateLookAt();
} }
} }
@@ -206,7 +188,6 @@ void ALuprexGameModeBase::InitializeGlobalState()
FlxLockedWrapper w; FlxLockedWrapper w;
// Sanity checks. Make sure everything is clean. // Sanity checks. Make sure everything is clean.
checkf(!LuprexUpdateTask.IsRunning(), TEXT("There should be no thread here."));
checkf(w->engine == nullptr, TEXT("There should be no engine here.")); checkf(w->engine == nullptr, TEXT("There should be no engine here."));
// If we failed to initialize the wrapper, print an error message. // If we failed to initialize the wrapper, print an error message.
@@ -243,16 +224,14 @@ void ALuprexGameModeBase::InitializeGlobalState()
} }
} }
// If we successfully created a luprex engine, create a socket system and a worker thread. // If we successfully created a luprex engine, create a socket system.
if (Playing) { if (Playing) {
Sockets.Reset(FlxSockets::Create(w)); Sockets.Reset(FlxSockets::Create(w));
std::string error = Sockets->GetError(); std::string error = Sockets->GetError();
check(error.empty()); check(error.empty());
LuprexUpdateTask.Startup(this);
} }
if (Playing) { if (Playing) {
OnWorldPreActorTickHandle = FWorldDelegates::OnWorldPreActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPreActorTick);
OnWorldPostActorTickHandle = FWorldDelegates::OnWorldPostActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPostActorTick); OnWorldPostActorTickHandle = FWorldDelegates::OnWorldPostActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPostActorTick);
} }

View File

@@ -6,7 +6,6 @@
#include "Engine/HitResult.h" #include "Engine/HitResult.h"
#include "GameFramework/GameModeBase.h" #include "GameFramework/GameModeBase.h"
#include "LuprexSockets.h" #include "LuprexSockets.h"
#include "TriggeredTask.h"
#include "BreakToDebugger.h" #include "BreakToDebugger.h"
#include "LuprexGameModeBase.generated.h" #include "LuprexGameModeBase.generated.h"
@@ -14,7 +13,7 @@
* *
*/ */
UCLASS(BlueprintType) UCLASS(BlueprintType)
class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase, public FRunnable class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase
{ {
GENERATED_BODY() GENERATED_BODY()
@@ -80,13 +79,17 @@ public:
// It is up to the blueprint code to actually determine what we're looking at. // It is up to the blueprint code to actually determine what we're looking at.
void UpdateLookAt(); void UpdateLookAt();
// Pre-tick and post-tick functions. // If the engine wants a new copy of the lua source code,
void OnWorldPreActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); // provide it.
void OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); void UpdateLuaSourceCode();
// The run function is called by a background thread // Update Sockets and Lua. Feeds socket data into the luprex engine,
// to update luprex sockets and update luprex itself. // and also calls play_update, the main Lua update function that causes
virtual uint32 Run() override; // Luprex to execute the majority of all the Lua code that needs processing.
void UpdateSocketsAndLua();
// Post-tick function.
void OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds);
// Get the current Luprex Game Mode Base, given a Context object. // Get the current Luprex Game Mode Base, given a Context object.
static ALuprexGameModeBase *FromContext(const UObject *Context); static ALuprexGameModeBase *FromContext(const UObject *Context);
@@ -101,10 +104,7 @@ public:
UPROPERTY(EditAnywhere, Category="Debugging Tools") UPROPERTY(EditAnywhere, Category="Debugging Tools")
ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity; ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity;
// This utility runs the luprex update and socket update in a thread. // Luprex socket system.
FTriggeredTask LuprexUpdateTask;
// Luprex socket system. Aside from construction, only touched by Luprex thread.
TUniquePtr<FlxSockets> Sockets; TUniquePtr<FlxSockets> Sockets;
// True if 'BeginPlay' has been successfully completed. // True if 'BeginPlay' has been successfully completed.
@@ -122,8 +122,7 @@ public:
// When do we next rotate the cube. // When do we next rotate the cube.
float NextRotateCube = 1.0f; float NextRotateCube = 1.0f;
// These allow us to pre-tick and post-tick. // This allows us to post-tick.
FDelegateHandle OnWorldPreActorTickHandle;
FDelegateHandle OnWorldPostActorTickHandle; FDelegateHandle OnWorldPostActorTickHandle;
// The device that implements BreakToDebuggerLogVerbosity, above. // The device that implements BreakToDebuggerLogVerbosity, above.