Skip to content

Commit

Permalink
Merge pull request #607 from evo-lua/uws-loop-global
Browse files Browse the repository at this point in the history
Streamline the shared event loop code in preparation for future changes
  • Loading branch information
rdw-software authored Jan 7, 2025
2 parents 3c6a598 + fed0a05 commit dcb61b0
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 62 deletions.
47 changes: 0 additions & 47 deletions Runtime/LuaVirtualMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <optional>

#include "macros.hpp"
#include "uws_ffi.hpp"

#include "LuaVirtualMachine.hpp"

Expand All @@ -22,32 +21,6 @@ int onLuaError(lua_State* m_luaState) {
return EXIT_FAILURE; // It's an error, after all
}

void unregister_uws_handles(lua_State* m_luaState) {
lua_getglobal(m_luaState, "UWS_EVENT_LOOP");
void* userdataPointer = lua_touserdata(m_luaState, -1);

if(userdataPointer != nullptr) {
auto uwsEventLoop = static_cast<uWS::Loop*>(userdataPointer);
uws_ffi::unassignEventLoop(uwsEventLoop);

lua_pushnil(m_luaState);
lua_setglobal(m_luaState, "UWS_EVENT_LOOP");
}
lua_pop(m_luaState, 1);
}

int modified_os_exit(lua_State* m_luaState) {
// Should probably check for close=true here, but it seems uws can deal with it just fine
unregister_uws_handles(m_luaState);

// Have to move the original function before the arguments before calling it
lua_getfield(m_luaState, LUA_REGISTRYINDEX, "default_os_exit");
lua_insert(m_luaState, 1);
lua_call(m_luaState, lua_gettop(m_luaState) - 1, LUA_MULTRET);

return lua_gettop(m_luaState);
}

LuaVirtualMachine::LuaVirtualMachine() {
m_relativeStackOffset = 0;

Expand All @@ -60,16 +33,6 @@ LuaVirtualMachine::LuaVirtualMachine() {
// No need to modify the stack offset since this will never be popped
lua_pushcfunction(m_luaState, onLuaError);
m_onLuaErrorIndex = lua_gettop(m_luaState);

// Not pretty, but os.exit doesn't unassign the uws loop (which crashes the runtime if close=true)
lua_getglobal(m_luaState, "os");
lua_getfield(m_luaState, -1, "exit");
lua_setfield(m_luaState, LUA_REGISTRYINDEX, "default_os_exit");

lua_pushcfunction(m_luaState, modified_os_exit);
lua_setfield(m_luaState, -2, "exit");
lua_pop(m_luaState, 1);

this->CheckStack();
}

Expand Down Expand Up @@ -177,16 +140,6 @@ void LuaVirtualMachine::CreateGlobalNamespace(std::string name) {
lua_setglobal(m_luaState, name.c_str());
}

void LuaVirtualMachine::AssignGlobalVariable(std::string key, std::string value) {
lua_pushstring(m_luaState, value.c_str());
lua_setglobal(m_luaState, key.c_str());
}

void LuaVirtualMachine::AssignGlobalVariable(std::string key, void* lightUserdataPointer) {
lua_pushlightuserdata(m_luaState, lightUserdataPointer);
lua_setglobal(m_luaState, key.c_str());
}

bool LuaVirtualMachine::CheckStack() {
// The most basic of checks, to make sure all symmetrical PUSH/POP operations are in alignment...
if(m_relativeStackOffset != 0) {
Expand Down
2 changes: 0 additions & 2 deletions Runtime/LuaVirtualMachine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ class LuaVirtualMachine {
bool SetGlobalArgs(int argc, char* argv[]);
void BindStaticLibraryExports(std::string fieldName, void* staticExportsTable);
void CreateGlobalNamespace(std::string name);
void AssignGlobalVariable(std::string key, std::string value);
void AssignGlobalVariable(std::string key, void* lightUserdataPointer);
bool CheckStack();
lua_State* GetState();

Expand Down
58 changes: 58 additions & 0 deletions Runtime/SharedEventLoop.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once

#include "LuaVirtualMachine.hpp"
#include "uws_ffi.hpp"

#include <cassert>
#include <format>
#include <memory>
#include <stdexcept>

using namespace std;
using uws_loop_t = uWS::Loop*;

extern "C" {
#include "luv.h"
#include "uv.h"
}

class SharedEventLoop {
private:
shared_ptr<LuaVirtualMachine> m_mainThreadVM;

uv_loop_t m_uvMainLoop;
uws_loop_t m_uwsMainLoop;

public:
explicit SharedEventLoop(auto L) {
assert(L != nullptr);
m_mainThreadVM = L;

int errorCode = uv_loop_init(&m_uvMainLoop);
if(errorCode != 0) {
auto message = format("Failed to initialize shared event loop ({}: {})",
uv_err_name(errorCode), uv_strerror(errorCode));
throw runtime_error(message);
}

luv_set_loop(m_mainThreadVM->GetState(), &m_uvMainLoop);

auto uwsEventLoop = uws_ffi::assignEventLoop(&m_uvMainLoop);
assert(uwsEventLoop != nullptr);
m_uwsMainLoop = uwsEventLoop;
}

~SharedEventLoop() {
luv_set_loop(m_mainThreadVM->GetState(), nullptr);
uws_ffi::unassignEventLoop(m_uwsMainLoop);
}

void RunMainLoopUntilDone() {
// There's just a single main loop right now, but that'll probably need to change
int refCount = uv_run(&m_uvMainLoop, UV_RUN_DEFAULT);
if(refCount != 0) {
auto message = format("Main loop finished running, but there's {} active references", refCount);
throw runtime_error(message);
}
}
};
17 changes: 4 additions & 13 deletions Runtime/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,17 @@ extern "C" {
#include "webview_ffi.hpp"

#include "LuaVirtualMachine.hpp"
#include "SharedEventLoop.hpp"

int main(int argc, char* argv[]) {
std::unique_ptr<LuaVirtualMachine> luaVM = std::make_unique<LuaVirtualMachine>();
std::shared_ptr<LuaVirtualMachine> luaVM = std::make_shared<LuaVirtualMachine>();

argv = uv_setup_args(argc, argv); // Required on Linux (see https://github.com/libuv/libuv/issues/2845)
auto L = luaVM->GetState();
luaVM->SetGlobalArgs(argc, argv);

// In order to support multiple guests on the event loop, the runtime itself must own it
uv_loop_t sharedEventLoop;
int errorCode = uv_loop_init(&sharedEventLoop);
if(errorCode > 0) {
return luaL_error(L, "Failed to initialize shared event loop (%s: %s)\n", uv_err_name(errorCode), uv_strerror(errorCode));
}
luv_set_loop(L, &sharedEventLoop);
std::unique_ptr<SharedEventLoop> sharedEventLoop = std::make_unique<SharedEventLoop>(luaVM);

luaVM->LoadPackage("uv", luaopen_luv);
luaVM->LoadPackage("lpeg", luaopen_lpeg);
Expand Down Expand Up @@ -74,22 +70,17 @@ int main(int argc, char* argv[]) {
runtime_ffi::assignLuaState(L);
rml_ffi::assignLuaState(L);

auto uwsEventLoop = uws_ffi::assignEventLoop(&sharedEventLoop);
luaVM->AssignGlobalVariable("UWS_EVENT_LOOP", static_cast<void*>(uwsEventLoop));

std::string mainChunk = "local evo = require('evo'); return evo.run()";
std::string chunkName = "=(Lua entry point, at " FROM_HERE ")";

int success = luaVM->DoString(mainChunk, chunkName);
if(!success) {
std::cerr << "\t" << FROM_HERE << ": in function 'main'" << std::endl;

uws_ffi::unassignEventLoop(uwsEventLoop);
return EXIT_FAILURE;
}

uv_run(&sharedEventLoop, UV_RUN_DEFAULT);
sharedEventLoop->RunMainLoopUntilDone();

uws_ffi::unassignEventLoop(uwsEventLoop);
return EXIT_SUCCESS;
}

0 comments on commit dcb61b0

Please sign in to comment.