aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r--src/lanes.cpp114
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();