aboutsummaryrefslogtreecommitdiff
path: root/src/universe.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/universe.cpp79
1 files changed, 78 insertions, 1 deletions
diff --git a/src/universe.cpp b/src/universe.cpp
index 097c642..b63008a 100644
--- a/src/universe.cpp
+++ b/src/universe.cpp
@@ -41,6 +41,10 @@ extern LUAG_FUNC(linda);
41 41
42// ################################################################################################# 42// #################################################################################################
43 43
44static constexpr std::string_view kOnStateCreate{ "on_state_create" }; // update lanes.lua if the name changes!
45
46// #################################################################################################
47
44// xxh64 of string "kUniverseFullRegKey" generated at https://www.pelock.com/products/hash-calculator 48// xxh64 of string "kUniverseFullRegKey" generated at https://www.pelock.com/products/hash-calculator
45static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full }; 49static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full };
46 50
@@ -74,6 +78,48 @@ Universe::Universe()
74 78
75// ################################################################################################# 79// #################################################################################################
76 80
81void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, LookupMode const mode_)
82{
83 if (std::holds_alternative<std::nullptr_t>(onStateCreateFunc)) {
84 return;
85 }
86
87 STACK_CHECK_START_REL(L_, 0);
88 DEBUGSPEW_CODE(DebugSpew(U_) << "calling on_state_create()" << std::endl);
89 if (std::holds_alternative<lua_CFunction>(onStateCreateFunc)) {
90
91 // C function: recreate a closure in the new state, bypassing the lookup scheme
92 lua_pushcfunction(L_, std::get<lua_CFunction>(onStateCreateFunc)); // on_state_create()
93 } else { // Lua function located in the config table, copied when we opened "lanes.core"
94 LUA_ASSERT(from_, std::holds_alternative<uintptr_t>(onStateCreateFunc));
95 if (mode_ != LookupMode::LaneBody) {
96 // if attempting to call in a keeper state, do nothing because the function doesn't exist there
97 // this doesn't count as an error though
98 STACK_CHECK(L_, 0);
99 return;
100 }
101 kConfigRegKey.pushValue(L_); // L_: config
102 STACK_CHECK(L_, 1);
103 LuaType const _funcType{ luaG_getfield(L_, -1, kOnStateCreate) }; // L_: config on_state_create()
104 if (_funcType != LuaType::FUNCTION) {
105 raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data());
106 }
107 lua_remove(L_, -2); // L_: on_state_create()
108 }
109 STACK_CHECK(L_, 1);
110 // capture error and raise it in caller state
111 std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" };
112 luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>"
113 if (lua_pcall(L_, 1, 0, 0) != LUA_OK) {
114 raise_luaL_error(from_, "%s failed: \"%s\"", kOnStateCreate.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, -1).data() : luaG_typename(L_, -1).data());
115 }
116 STACK_CHECK(L_, 0);
117}
118
119
120
121// #################################################################################################
122
77// only called from the master state 123// only called from the master state
78[[nodiscard]] Universe* Universe::Create(lua_State* const L_) 124[[nodiscard]] Universe* Universe::Create(lua_State* const L_)
79{ 125{
@@ -125,7 +171,7 @@ Universe::Universe()
125 // Linked chains handling 171 // Linked chains handling
126 _U->selfdestructFirst = SELFDESTRUCT_END; 172 _U->selfdestructFirst = SELFDESTRUCT_END;
127 _U->initializeAllocatorFunction(L_); 173 _U->initializeAllocatorFunction(L_);
128 state::InitializeOnStateCreate(_U, L_); 174 _U->initializeOnStateCreate(L_);
129 _U->keepers.initialize(*_U, L_, _nbUserKeepers, _keepers_gc_threshold); 175 _U->keepers.initialize(*_U, L_, _nbUserKeepers, _keepers_gc_threshold);
130 STACK_CHECK(L_, 0); 176 STACK_CHECK(L_, 0);
131 177
@@ -252,6 +298,37 @@ int Universe::InitializeFinalizer(lua_State* const L_)
252 298
253// ################################################################################################# 299// #################################################################################################
254 300
301void Universe::initializeOnStateCreate(lua_State* const L_)
302{
303 STACK_CHECK_START_REL(L_, 1); // L_: settings
304 if (luaG_getfield(L_, -1, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil
305 LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation
306 // make sure the function doesn't have upvalues
307 char const* _upname{ lua_getupvalue(L_, -1, 1) }; // L_: settings on_state_create upval?
308 if (_upname != nullptr) { // should be "" for C functions with upvalues if any
309 raise_luaL_error(L_, "%s with upvalues are forbidden", kOnStateCreate.data());
310 }
311 // store C function pointer in an internal variable
312 lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create
313 if (_func) {
314 onStateCreateFunc.emplace<lua_CFunction>(_func);
315 // remove this C function from the config table so that it doesn't cause problems
316 // when we transfer the config table in newly created Lua states
317 lua_pushnil(L_); // L_: settings on_state_create nil
318 luaG_setfield(L_, -3, kOnStateCreate); // L_: settings on_state_create
319 } else {
320 // the function is still in the config table
321 onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data()));
322 }
323 } else {
324 LUA_ASSERT(L_, std::holds_alternative<std::nullptr_t>(onStateCreateFunc));
325 };
326 lua_pop(L_, 1); // L_: settings
327 STACK_CHECK(L_, 1);
328}
329
330// #################################################################################################
331
255lanes::AllocatorDefinition Universe::resolveAllocator(lua_State* const L_, std::string_view const& hint_) const 332lanes::AllocatorDefinition Universe::resolveAllocator(lua_State* const L_, std::string_view const& hint_) const
256{ 333{
257 lanes::AllocatorDefinition _ret{ protectedAllocator }; 334 lanes::AllocatorDefinition _ret{ protectedAllocator };