diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2026-03-02 18:12:39 +0100 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2026-03-02 18:12:39 +0100 |
| commit | 4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0 (patch) | |
| tree | 0b50dfc070260d285baeae6f12b78e1e8a4d6811 /src | |
| parent | a225b7808dd1d672f3e74ae5ac0af0f9f9322314 (diff) | |
| download | lanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.tar.gz lanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.tar.bz2 lanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.zip | |
lane_new internal code cleanup step 3: RequireModulesInLane
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.cpp | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index cdf5f5a..edcc556 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -293,6 +293,55 @@ namespace { | |||
| 293 | [[maybe_unused]] InterCopyResult const _ret{ _c.interCopyPackage() }; | 293 | [[maybe_unused]] InterCopyResult const _ret{ _c.interCopyPackage() }; |
| 294 | LUA_ASSERT(L_, _ret == InterCopyResult::Success); // either all went well, or we should not even get here | 294 | LUA_ASSERT(L_, _ret == InterCopyResult::Success); // either all went well, or we should not even get here |
| 295 | } | 295 | } |
| 296 | |||
| 297 | // require() each module listed in requiredIdx_ inside the lane state, then register its | ||
| 298 | // exported functions in the lookup table. No-op when requiredIdx_ is nil/none. | ||
| 299 | static void RequireModulesInLane(Universe* const U_, lua_State* const L_, lua_State* const L2_, StackIndex const requiredIdx_) | ||
| 300 | { | ||
| 301 | if (lua_isnoneornil(L_, requiredIdx_)) { | ||
| 302 | return; | ||
| 303 | } | ||
| 304 | DEBUGSPEW_CODE(DebugSpew(U_) << "lane_new: process 'required' list" << std::endl); | ||
| 305 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); | ||
| 306 | // should not happen, was checked in lanes.lua before calling lane_new() | ||
| 307 | if (luaW_type(L_, requiredIdx_) != LuaType::TABLE) { | ||
| 308 | raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, requiredIdx_)); | ||
| 309 | } | ||
| 310 | |||
| 311 | int _nbRequired{ 1 }; | ||
| 312 | lua_pushnil(L_); // L_: [fixed] args... nil L2: | ||
| 313 | while (lua_next(L_, requiredIdx_) != 0) { // L_: [fixed] args... n "modname" L2: | ||
| 314 | if (luaW_type(L_, kIdxTop) != LuaType::STRING || luaW_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) { | ||
| 315 | raise_luaL_error(L_, "required module list should be a list of strings"); | ||
| 316 | } else { | ||
| 317 | // require the module in the target state, and populate the lookup table there too | ||
| 318 | std::string_view const _name{ luaW_tostring(L_, kIdxTop) }; | ||
| 319 | DEBUGSPEW_CODE(DebugSpew(U_) << "lane_new: require '" << _name << "'" << std::endl); | ||
| 320 | |||
| 321 | // require the module in the target lane | ||
| 322 | lua_getglobal(L2_, "require"); // L_: [fixed] args... n "modname" L2: require()? | ||
| 323 | if (lua_isnil(L2_, -1)) { | ||
| 324 | lua_pop(L2_, 1); // L_: [fixed] args... n "modname" L2: | ||
| 325 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); | ||
| 326 | } else { | ||
| 327 | luaW_pushstring(L2_, _name); // L_: [fixed] args... n "modname" L2: require() name | ||
| 328 | LuaError const _rc{ lua_pcall(L2_, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode | ||
| 329 | if (_rc != LuaError::OK) { | ||
| 330 | // propagate error to main state if any | ||
| 331 | InterCopyContext _c{ U_, DestState{ L_ }, SourceState{ L2_ }, {}, {}, {}, {}, {} }; | ||
| 332 | std::ignore = _c.interMove(1); // L_: [fixed] args... n "modname" error L2: | ||
| 333 | raise_lua_error(L_); | ||
| 334 | } | ||
| 335 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret | ||
| 336 | // after requiring the module, register the functions it exported in our name<->function database | ||
| 337 | tools::PopulateFuncLookupTable(L2_, kIdxTop, _name); | ||
| 338 | lua_pop(L2_, 1); // L_: [fixed] args... n "modname" L2: | ||
| 339 | } | ||
| 340 | } | ||
| 341 | lua_pop(L_, 1); // L_: [fixed] args... n L2: | ||
| 342 | ++_nbRequired; | ||
| 343 | } // L_: [fixed] args... | ||
| 344 | } | ||
| 296 | } // namespace local | 345 | } // namespace local |
| 297 | } // namespace | 346 | } // namespace |
| 298 | 347 | ||
| @@ -336,7 +385,7 @@ LUAG_FUNC(lane_new) | |||
| 336 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); | 385 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); |
| 337 | 386 | ||
| 338 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaW_tostring(L_, kLibsIdx)) }; | 387 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaW_tostring(L_, kLibsIdx)) }; |
| 339 | lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: | 388 | lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: |
| 340 | STACK_CHECK_START_REL(_S, 0); | 389 | STACK_CHECK_START_REL(_S, 0); |
| 341 | 390 | ||
| 342 | // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 391 | // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
| @@ -478,49 +527,7 @@ LUAG_FUNC(lane_new) | |||
| 478 | STACK_CHECK(_L2, 0); | 527 | STACK_CHECK(_L2, 0); |
| 479 | 528 | ||
| 480 | // modules to require in the target lane *before* the function is transfered! | 529 | // modules to require in the target lane *before* the function is transfered! |
| 481 | StackIndex const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? kIdxNone : kRequIdx }; | 530 | local::RequireModulesInLane(_U, L_, _L2, kRequIdx); |
| 482 | if (_required_idx != 0) { | ||
| 483 | int _nbRequired{ 1 }; | ||
| 484 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); | ||
| 485 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | ||
| 486 | // should not happen, was checked in lanes.lua before calling lane_new() | ||
| 487 | if (luaW_type(L_, _required_idx) != LuaType::TABLE) { | ||
| 488 | raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx)); | ||
| 489 | } | ||
| 490 | |||
| 491 | lua_pushnil(L_); // L_: [fixed] args... nil L2: | ||
| 492 | while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2: | ||
| 493 | if (luaW_type(L_, kIdxTop) != LuaType::STRING || luaW_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) { | ||
| 494 | raise_luaL_error(L_, "required module list should be a list of strings"); | ||
| 495 | } else { | ||
| 496 | // require the module in the target state, and populate the lookup table there too | ||
| 497 | std::string_view const _name{ luaW_tostring(L_, kIdxTop) }; | ||
| 498 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); | ||
| 499 | |||
| 500 | // require the module in the target lane | ||
| 501 | lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? | ||
| 502 | if (lua_isnil(_L2, -1)) { | ||
| 503 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | ||
| 504 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); | ||
| 505 | } else { | ||
| 506 | luaW_pushstring(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name | ||
| 507 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode | ||
| 508 | if (_rc != LuaError::OK) { | ||
| 509 | // propagate error to main state if any | ||
| 510 | InterCopyContext _c{ _U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; | ||
| 511 | std::ignore = _c.interMove(1); // L_: [fixed] args... n "modname" error L2: | ||
| 512 | raise_lua_error(L_); | ||
| 513 | } | ||
| 514 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret | ||
| 515 | // after requiring the module, register the functions it exported in our name<->function database | ||
| 516 | tools::PopulateFuncLookupTable(_L2, kIdxTop, _name); | ||
| 517 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | ||
| 518 | } | ||
| 519 | } | ||
| 520 | lua_pop(L_, 1); // L_: [fixed] args... n L2: | ||
| 521 | ++_nbRequired; | ||
| 522 | } // L_: [fixed] args... | ||
| 523 | } | ||
| 524 | STACK_CHECK(L_, 0); | 531 | STACK_CHECK(L_, 0); |
| 525 | STACK_CHECK(_L2, 0); // L_: [fixed] args... L2: | 532 | STACK_CHECK(_L2, 0); // L_: [fixed] args... L2: |
| 526 | 533 | ||
