diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2026-03-02 18:35:09 +0100 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2026-03-02 18:35:09 +0100 |
| commit | fb88deef1a21645176bdd0f2a52ac36f43a8e8f7 (patch) | |
| tree | 3f32c1d90857321d821c2f15fc8947318b70ba3f /src | |
| parent | 2b5086f4e794b0b83b1493de80eb6e4b6c67797b (diff) | |
| download | lanes-fb88deef1a21645176bdd0f2a52ac36f43a8e8f7.tar.gz lanes-fb88deef1a21645176bdd0f2a52ac36f43a8e8f7.tar.bz2 lanes-fb88deef1a21645176bdd0f2a52ac36f43a8e8f7.zip | |
lane_new internal code cleanup step 7: PrepareLaneUserData
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.cpp | 114 |
1 files changed, 57 insertions, 57 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 17380f6..5b9eb2b 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -412,6 +412,61 @@ namespace { | |||
| 412 | raise_luaL_error(L_, "tried to copy unsupported types"); | 412 | raise_luaL_error(L_, "tried to copy unsupported types"); |
| 413 | } | 413 | } |
| 414 | } | 414 | } |
| 415 | |||
| 416 | // Create and push the Lane full userdata onto L_, attach its metatable (upvalue 1) and a | ||
| 417 | // uservalue table, optionally store the gc_cb callback, and set the lane's debug name. | ||
| 418 | static void PrepareLaneUserData(lua_State* const L_, Lane* const lane_, StackIndex const gcCbIdx_, StackIndex const nameIdx_, StackIndex const funcIdx_) | ||
| 419 | { | ||
| 420 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "lane_new: preparing lane userdata" << std::endl); | ||
| 421 | STACK_CHECK_START_REL(L_, 0); | ||
| 422 | // a Lane full userdata needs a single uservalue | ||
| 423 | Lane** const _ud{ luaW_newuserdatauv<Lane*>(L_, UserValueCount{ 1 }) }; // L_: ... lane | ||
| 424 | *_ud = lane_; // don't forget to store the pointer in the userdata! | ||
| 425 | |||
| 426 | // Set metatable for the userdata | ||
| 427 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: ... lane mt | ||
| 428 | lua_setmetatable(L_, -2); // L_: ... lane | ||
| 429 | STACK_CHECK(L_, 1); | ||
| 430 | |||
| 431 | // Create uservalue for the userdata. There can be only one that must be a table, due to Lua 5.1 compatibility. | ||
| 432 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) | ||
| 433 | lua_newtable(L_); // L_: ... lane {uv} | ||
| 434 | |||
| 435 | // Store the gc_cb callback in the uservalue | ||
| 436 | StackIndex const _gc_cb_idx{ lua_isnoneornil(L_, gcCbIdx_) ? kIdxNone : gcCbIdx_ }; | ||
| 437 | if (_gc_cb_idx > 0) { | ||
| 438 | kLaneGC.pushKey(L_); // L_: ... lane {uv} k | ||
| 439 | lua_pushvalue(L_, _gc_cb_idx); // L_: ... lane {uv} k gc_cb | ||
| 440 | lua_rawset(L_, -3); // L_: ... lane {uv} | ||
| 441 | } | ||
| 442 | STACK_CHECK(L_, 2); | ||
| 443 | // store the uservalue in the Lane full userdata | ||
| 444 | lua_setiuservalue(L_, StackIndex{ -2 }, UserValueIndex{ 1 }); // L_: ... lane | ||
| 445 | |||
| 446 | StackIndex const _name_idx{ lua_isnoneornil(L_, nameIdx_) ? kIdxNone : nameIdx_ }; | ||
| 447 | std::string_view _debugName{ (_name_idx > 0) ? luaW_tostring(L_, _name_idx) : std::string_view{} }; | ||
| 448 | if (!_debugName.empty()) { | ||
| 449 | if (_debugName == "auto") { | ||
| 450 | if (luaW_type(L_, funcIdx_) == LuaType::STRING) { | ||
| 451 | lua_Debug _ar; | ||
| 452 | if (lua_getstack(L_, 2, &_ar) == 0) { // 0 is here, 1 is lanes.gen, 2 is its caller | ||
| 453 | lua_getstack(L_, 1, &_ar); // level 2 may not exist with LuaJIT, try again with level 1 | ||
| 454 | } | ||
| 455 | lua_getinfo(L_, "Sl", &_ar); | ||
| 456 | luaW_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: ... lane "<name>" | ||
| 457 | } else { | ||
| 458 | lua_Debug _ar; | ||
| 459 | lua_pushvalue(L_, funcIdx_); // L_: ... lane func | ||
| 460 | lua_getinfo(L_, ">S", &_ar); // L_: ... lane | ||
| 461 | luaW_pushstring(L_, "%s:%d", _ar.short_src, _ar.linedefined); // L_: ... lane "<name>" | ||
| 462 | } | ||
| 463 | lua_replace(L_, _name_idx); // L_: ... lane | ||
| 464 | _debugName = luaW_tostring(L_, _name_idx); | ||
| 465 | } | ||
| 466 | lane_->storeDebugName(_debugName); | ||
| 467 | } | ||
| 468 | STACK_CHECK(L_, 1); | ||
| 469 | } | ||
| 415 | } // namespace local | 470 | } // namespace local |
| 416 | } // namespace | 471 | } // namespace |
| 417 | 472 | ||
| @@ -489,7 +544,7 @@ LUAG_FUNC(lane_new) | |||
| 489 | if (lane) { | 544 | if (lane) { |
| 490 | STACK_CHECK_START_REL(L, 0); | 545 | STACK_CHECK_START_REL(L, 0); |
| 491 | // we still need a full userdata so that garbage collection can do its thing | 546 | // we still need a full userdata so that garbage collection can do its thing |
| 492 | prepareUserData(); | 547 | local::PrepareLaneUserData(L, lane, kGcCbIdx, kNameIdx, kFuncIdx); |
| 493 | // remove it immediately from the stack so that the error that landed us here is at the top | 548 | // remove it immediately from the stack so that the error that landed us here is at the top |
| 494 | lua_pop(L, 1); | 549 | lua_pop(L, 1); |
| 495 | STACK_CHECK(L, 0); | 550 | STACK_CHECK(L, 0); |
| @@ -510,65 +565,10 @@ LUAG_FUNC(lane_new) | |||
| 510 | } | 565 | } |
| 511 | } | 566 | } |
| 512 | 567 | ||
| 513 | private: | ||
| 514 | void prepareUserData() | ||
| 515 | { | ||
| 516 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); | ||
| 517 | STACK_CHECK_START_REL(L, 0); | ||
| 518 | // a Lane full userdata needs a single uservalue | ||
| 519 | Lane** const _ud{ luaW_newuserdatauv<Lane*>(L, UserValueCount{ 1 }) }; // L: ... lane | ||
| 520 | *_ud = lane; // don't forget to store the pointer in the userdata! | ||
| 521 | |||
| 522 | // Set metatable for the userdata | ||
| 523 | lua_pushvalue(L, lua_upvalueindex(1)); // L: ... lane mt | ||
| 524 | lua_setmetatable(L, -2); // L: ... lane | ||
| 525 | STACK_CHECK(L, 1); | ||
| 526 | |||
| 527 | // Create uservalue for the userdata. There can be only one that must be a table, due to Lua 5.1 compatibility. | ||
| 528 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) | ||
| 529 | lua_newtable(L); // L: ... lane {uv} | ||
| 530 | |||
| 531 | // Store the gc_cb callback in the uservalue | ||
| 532 | StackIndex const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? kIdxNone : kGcCbIdx }; | ||
| 533 | if (_gc_cb_idx > 0) { | ||
| 534 | kLaneGC.pushKey(L); // L: ... lane {uv} k | ||
| 535 | lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb | ||
| 536 | lua_rawset(L, -3); // L: ... lane {uv} | ||
| 537 | } | ||
| 538 | STACK_CHECK(L, 2); | ||
| 539 | // store the uservalue in the Lane full userdata | ||
| 540 | lua_setiuservalue(L, StackIndex{ -2 }, UserValueIndex{ 1 }); // L: ... lane | ||
| 541 | |||
| 542 | StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? kIdxNone : kNameIdx }; | ||
| 543 | std::string_view _debugName{ (_name_idx > 0) ? luaW_tostring(L, _name_idx) : std::string_view{} }; | ||
| 544 | if (!_debugName.empty()) | ||
| 545 | { | ||
| 546 | if (_debugName == "auto") { | ||
| 547 | if (luaW_type(L, kFuncIdx) == LuaType::STRING) { | ||
| 548 | lua_Debug _ar; | ||
| 549 | if (lua_getstack(L, 2, &_ar) == 0) { // 0 is here, 1 is lanes.gen, 2 is its caller | ||
| 550 | lua_getstack(L, 1, &_ar); // level 2 may not exist with LuaJIT, try again with level 1 | ||
| 551 | } | ||
| 552 | lua_getinfo(L, "Sl", &_ar); | ||
| 553 | luaW_pushstring(L, "%s:%d", _ar.short_src, _ar.currentline); // L: ... lane "<name>" | ||
| 554 | } else { | ||
| 555 | lua_Debug _ar; | ||
| 556 | lua_pushvalue(L, kFuncIdx); // L: ... lane func | ||
| 557 | lua_getinfo(L, ">S", &_ar); // L: ... lane | ||
| 558 | luaW_pushstring(L, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane "<name>" | ||
| 559 | } | ||
| 560 | lua_replace(L, _name_idx); // L: ... lane | ||
| 561 | _debugName = luaW_tostring(L, _name_idx); | ||
| 562 | } | ||
| 563 | lane->storeDebugName(_debugName); | ||
| 564 | } | ||
| 565 | STACK_CHECK(L, 1); | ||
| 566 | } | ||
| 567 | |||
| 568 | public: | 568 | public: |
| 569 | void success() | 569 | void success() |
| 570 | { | 570 | { |
| 571 | prepareUserData(); | 571 | local::PrepareLaneUserData(L, lane, kGcCbIdx, kNameIdx, kFuncIdx); |
| 572 | // unblock the thread so that it can terminate gracefully | 572 | // unblock the thread so that it can terminate gracefully |
| 573 | #ifndef __PROSPERO__ | 573 | #ifndef __PROSPERO__ |
| 574 | lane->ready.count_down(); | 574 | lane->ready.count_down(); |
