aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r--src/lanes.cpp823
1 files changed, 411 insertions, 412 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp
index e150eea..d87d93e 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -202,22 +202,22 @@ void Lane::startThread(int priority_)
202#define ERROR_FULL_STACK 1 // must be either 0 or 1 as we do some index arithmetics with it! 202#define ERROR_FULL_STACK 1 // must be either 0 or 1 as we do some index arithmetics with it!
203 203
204// intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed 204// intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed
205static void securize_debug_threadname(lua_State* L, Lane* lane_) 205static void securize_debug_threadname(lua_State* L_, Lane* lane_)
206{ 206{
207 STACK_CHECK_START_REL(L, 0); 207 STACK_CHECK_START_REL(L_, 0);
208 STACK_GROW(L, 3); 208 STACK_GROW(L_, 3);
209 lua_getiuservalue(L, 1, 1); 209 lua_getiuservalue(L_, 1, 1);
210 lua_newtable(L); 210 lua_newtable(L_);
211 // Lua 5.1 can't do 'lane_->debug_name = lua_pushstring(L, lane_->debug_name);' 211 // Lua 5.1 can't do 'lane_->debug_name = lua_pushstring(L, lane_->debug_name);'
212 lua_pushstring(L, lane_->debug_name); 212 lua_pushstring(L_, lane_->debug_name);
213 lane_->debug_name = lua_tostring(L, -1); 213 lane_->debug_name = lua_tostring(L_, -1);
214 lua_rawset(L, -3); 214 lua_rawset(L_, -3);
215 lua_pop(L, 1); 215 lua_pop(L_, 1);
216 STACK_CHECK(L, 0); 216 STACK_CHECK(L_, 0);
217} 217}
218 218
219#if ERROR_FULL_STACK 219#if ERROR_FULL_STACK
220[[nodiscard]] static int lane_error(lua_State* L); 220[[nodiscard]] static int lane_error(lua_State* L_);
221// xxh64 of string "kStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator 221// xxh64 of string "kStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator
222static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull }; 222static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull };
223#endif // ERROR_FULL_STACK 223#endif // ERROR_FULL_STACK
@@ -255,20 +255,20 @@ Lane::~Lane()
255 255
256// Push the finalizers table on the stack. 256// Push the finalizers table on the stack.
257// If there is no existing table, create ti. 257// If there is no existing table, create ti.
258static void push_finalizers_table(lua_State* L) 258static void push_finalizers_table(lua_State* L_)
259{ 259{
260 STACK_GROW(L, 3); 260 STACK_GROW(L_, 3);
261 STACK_CHECK_START_REL(L, 0); 261 STACK_CHECK_START_REL(L_, 0);
262 262
263 kFinalizerRegKey.pushValue(L); // ? 263 kFinalizerRegKey.pushValue(L_); // ?
264 if (lua_isnil(L, -1)) // nil? 264 if (lua_isnil(L_, -1)) // nil?
265 { 265 {
266 lua_pop(L, 1); // 266 lua_pop(L_, 1); //
267 // store a newly created table in the registry, but leave it on the stack too 267 // store a newly created table in the registry, but leave it on the stack too
268 lua_newtable(L); // t 268 lua_newtable(L_); // t
269 kFinalizerRegKey.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // t 269 kFinalizerRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); // t
270 } 270 }
271 STACK_CHECK(L, 1); 271 STACK_CHECK(L_, 1);
272} 272}
273 273
274// ################################################################################################# 274// #################################################################################################
@@ -283,21 +283,21 @@ static void push_finalizers_table(lua_State* L)
283// 283//
284LUAG_FUNC(set_finalizer) 284LUAG_FUNC(set_finalizer)
285{ 285{
286 luaL_argcheck(L, lua_isfunction(L, 1), 1, "finalizer should be a function"); 286 luaL_argcheck(L_, lua_isfunction(L_, 1), 1, "finalizer should be a function");
287 luaL_argcheck(L, lua_gettop( L) == 1, 1, "too many arguments"); 287 luaL_argcheck(L_, lua_gettop(L_) == 1, 1, "too many arguments");
288 // Get the current finalizer table (if any), create one if it doesn't exist 288 // Get the current finalizer table (if any), create one if it doesn't exist
289 push_finalizers_table(L); // finalizer {finalisers} 289 push_finalizers_table(L_); // finalizer {finalisers}
290 STACK_GROW(L, 2); 290 STACK_GROW(L_, 2);
291 lua_pushinteger(L, lua_rawlen(L, -1) + 1); // finalizer {finalisers} idx 291 lua_pushinteger(L_, lua_rawlen(L_, -1) + 1); // finalizer {finalisers} idx
292 lua_pushvalue(L, 1); // finalizer {finalisers} idx finalizer 292 lua_pushvalue(L_, 1); // finalizer {finalisers} idx finalizer
293 lua_rawset(L, -3); // finalizer {finalisers} 293 lua_rawset(L_, -3); // finalizer {finalisers}
294 lua_pop(L, 2); // 294 lua_pop(L_, 2);
295 return 0; 295 return 0;
296} 296}
297 297
298// ################################################################################################# 298// #################################################################################################
299 299
300static void push_stack_trace(lua_State* L, int rc_, int stk_base_) 300static void push_stack_trace(lua_State* L_, int rc_, int stk_base_)
301{ 301{
302 // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry 302 // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry
303 switch(rc_) 303 switch(rc_)
@@ -308,16 +308,16 @@ static void push_stack_trace(lua_State* L, int rc_, int stk_base_)
308 case LUA_ERRRUN: // cancellation or a runtime error 308 case LUA_ERRRUN: // cancellation or a runtime error
309#if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler 309#if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler
310 { 310 {
311 STACK_CHECK_START_REL(L, 0); 311 STACK_CHECK_START_REL(L_, 0);
312 // fetch the call stack table from the registry where the handler stored it 312 // fetch the call stack table from the registry where the handler stored it
313 STACK_GROW(L, 1); 313 STACK_GROW(L_, 1);
314 // yields nil if no stack was generated (in case of cancellation for example) 314 // yields nil if no stack was generated (in case of cancellation for example)
315 kStackTraceRegKey.pushValue(L); // err trace|nil 315 kStackTraceRegKey.pushValue(L_); // err trace|nil
316 STACK_CHECK(L, 1); 316 STACK_CHECK(L_, 1);
317 317
318 // For cancellation the error message is kCancelError, and a stack trace isn't placed 318 // For cancellation the error message is kCancelError, and a stack trace isn't placed
319 // For other errors, the message can be whatever was thrown, and we should have a stack trace table 319 // For other errors, the message can be whatever was thrown, and we should have a stack trace table
320 LUA_ASSERT(L, lua_type(L, 1 + stk_base_) == (kCancelError.equals(L, stk_base_) ? LUA_TNIL : LUA_TTABLE)); 320 LUA_ASSERT(L_, lua_type(L_, 1 + stk_base_) == (kCancelError.equals(L_, stk_base_) ? LUA_TNIL : LUA_TTABLE));
321 // Just leaving the stack trace table on the stack is enough to get it through to the master. 321 // Just leaving the stack trace table on the stack is enough to get it through to the master.
322 break; 322 break;
323 } 323 }
@@ -327,7 +327,7 @@ static void push_stack_trace(lua_State* L, int rc_, int stk_base_)
327 case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) 327 case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition)
328 default: 328 default:
329 // we should have a single value which is either a string (the error message) or kCancelError 329 // we should have a single value which is either a string (the error message) or kCancelError
330 LUA_ASSERT(L, (lua_gettop(L) == stk_base_) && ((lua_type(L, stk_base_) == LUA_TSTRING) || kCancelError.equals(L, stk_base_))); 330 LUA_ASSERT(L_, (lua_gettop(L_) == stk_base_) && ((lua_type(L_, stk_base_) == LUA_TSTRING) || kCancelError.equals(L_, stk_base_)));
331 break; 331 break;
332 } 332 }
333} 333}
@@ -347,45 +347,45 @@ static void push_stack_trace(lua_State* L, int rc_, int stk_base_)
347// TBD: should we add stack trace on failing finalizer, wouldn't be hard.. 347// TBD: should we add stack trace on failing finalizer, wouldn't be hard..
348// 348//
349 349
350[[nodiscard]] static int run_finalizers(lua_State* L, int lua_rc_) 350[[nodiscard]] static int run_finalizers(lua_State* L_, int lua_rc_)
351{ 351{
352 kFinalizerRegKey.pushValue(L); // ... finalizers? 352 kFinalizerRegKey.pushValue(L_); // ... finalizers?
353 if (lua_isnil(L, -1)) 353 if (lua_isnil(L_, -1))
354 { 354 {
355 lua_pop(L, 1); 355 lua_pop(L_, 1);
356 return 0; // no finalizers 356 return 0; // no finalizers
357 } 357 }
358 358
359 STACK_GROW(L, 5); 359 STACK_GROW(L_, 5);
360 360
361 int const finalizers_index{ lua_gettop(L) }; 361 int const finalizers_index{ lua_gettop(L_) };
362 int const err_handler_index{ ERROR_FULL_STACK ? (lua_pushcfunction(L, lane_error), lua_gettop(L)) : 0 }; 362 int const err_handler_index{ ERROR_FULL_STACK ? (lua_pushcfunction(L_, lane_error), lua_gettop(L_)) : 0 };
363 363
364 int rc{ LUA_OK }; 364 int rc{ LUA_OK };
365 for (int n = static_cast<int>(lua_rawlen(L, finalizers_index)); n > 0; --n) 365 for (int n = static_cast<int>(lua_rawlen(L_, finalizers_index)); n > 0; --n)
366 { 366 {
367 int args = 0; 367 int args = 0;
368 lua_pushinteger(L, n); // ... finalizers lane_error n 368 lua_pushinteger(L_, n); // ... finalizers lane_error n
369 lua_rawget(L, finalizers_index); // ... finalizers lane_error finalizer 369 lua_rawget(L_, finalizers_index); // ... finalizers lane_error finalizer
370 LUA_ASSERT(L, lua_isfunction(L, -1)); 370 LUA_ASSERT(L_, lua_isfunction(L_, -1));
371 if (lua_rc_ != LUA_OK) // we have an error message and an optional stack trace at the bottom of the stack 371 if (lua_rc_ != LUA_OK) // we have an error message and an optional stack trace at the bottom of the stack
372 { 372 {
373 LUA_ASSERT(L, finalizers_index == 2 || finalizers_index == 3); 373 LUA_ASSERT(L_, finalizers_index == 2 || finalizers_index == 3);
374 //char const* err_msg = lua_tostring(L, 1); 374 //char const* err_msg = lua_tostring(L, 1);
375 lua_pushvalue(L, 1); // ... finalizers lane_error finalizer err_msg 375 lua_pushvalue(L_, 1); // ... finalizers lane_error finalizer err_msg
376 // note we don't always have a stack trace for example when kCancelError, or when we got an error that doesn't call our handler, such as LUA_ERRMEM 376 // note we don't always have a stack trace for example when kCancelError, or when we got an error that doesn't call our handler, such as LUA_ERRMEM
377 if (finalizers_index == 3) 377 if (finalizers_index == 3)
378 { 378 {
379 lua_pushvalue(L, 2); // ... finalizers lane_error finalizer err_msg stack_trace 379 lua_pushvalue(L_, 2); // ... finalizers lane_error finalizer err_msg stack_trace
380 } 380 }
381 args = finalizers_index - 1; 381 args = finalizers_index - 1;
382 } 382 }
383 383
384 // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace 384 // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace
385 rc = lua_pcall(L, args, 0, err_handler_index); // ... finalizers lane_error err_msg2? 385 rc = lua_pcall(L_, args, 0, err_handler_index); // ... finalizers lane_error err_msg2?
386 if (rc != LUA_OK) 386 if (rc != LUA_OK)
387 { 387 {
388 push_stack_trace(L, rc, lua_gettop(L)); 388 push_stack_trace(L_, rc, lua_gettop(L_));
389 // If one finalizer fails, don't run the others. Return this 389 // If one finalizer fails, don't run the others. Return this
390 // as the 'real' error, replacing what we could have had (or not) 390 // as the 'real' error, replacing what we could have had (or not)
391 // from the actual code. 391 // from the actual code.
@@ -397,18 +397,18 @@ static void push_stack_trace(lua_State* L, int rc_, int stk_base_)
397 if (rc != LUA_OK) 397 if (rc != LUA_OK)
398 { 398 {
399 // ERROR_FULL_STACK accounts for the presence of lane_error on the stack 399 // ERROR_FULL_STACK accounts for the presence of lane_error on the stack
400 int const nb_err_slots{ lua_gettop(L) - finalizers_index - ERROR_FULL_STACK }; 400 int const nb_err_slots{ lua_gettop(L_) - finalizers_index - ERROR_FULL_STACK };
401 // a finalizer generated an error, this is what we leave of the stack 401 // a finalizer generated an error, this is what we leave of the stack
402 for (int n = nb_err_slots; n > 0; --n) 402 for (int n = nb_err_slots; n > 0; --n)
403 { 403 {
404 lua_replace(L, n); 404 lua_replace(L_, n);
405 } 405 }
406 // leave on the stack only the error and optional stack trace produced by the error in the finalizer 406 // leave on the stack only the error and optional stack trace produced by the error in the finalizer
407 lua_settop(L, nb_err_slots); 407 lua_settop(L_, nb_err_slots);
408 } 408 }
409 else // no error from the finalizers, make sure only the original return values from the lane body remain on the stack 409 else // no error from the finalizers, make sure only the original return values from the lane body remain on the stack
410 { 410 {
411 lua_settop(L, finalizers_index - 1); 411 lua_settop(L_, finalizers_index - 1);
412 } 412 }
413 413
414 return rc; 414 return rc;
@@ -481,11 +481,11 @@ static void selfdestruct_add(Lane* lane_)
481/* 481/*
482* Process end; cancel any still free-running threads 482* Process end; cancel any still free-running threads
483*/ 483*/
484[[nodiscard]] static int universe_gc(lua_State* L) 484[[nodiscard]] static int universe_gc(lua_State* L_)
485{ 485{
486 Universe* const U{ lua_tofulluserdata<Universe>(L, 1) }; 486 Universe* const U{ lua_tofulluserdata<Universe>(L_, 1) };
487 lua_Duration const shutdown_timeout{ lua_tonumber(L, lua_upvalueindex(1)) }; 487 lua_Duration const shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) };
488 [[maybe_unused]] char const* const op_string{ lua_tostring(L, lua_upvalueindex(2)) }; 488 [[maybe_unused]] char const* const op_string{ lua_tostring(L_, lua_upvalueindex(2)) };
489 CancelOp const op{ which_cancel_op(op_string) }; 489 CancelOp const op{ which_cancel_op(op_string) };
490 490
491 if (U->selfdestruct_first != SELFDESTRUCT_END) 491 if (U->selfdestruct_first != SELFDESTRUCT_END)
@@ -556,7 +556,7 @@ static void selfdestruct_add(Lane* lane_)
556 if (lane != SELFDESTRUCT_END) 556 if (lane != SELFDESTRUCT_END)
557 { 557 {
558 // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it) 558 // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it)
559 raise_luaL_error(L, "Zombie thread %s refuses to die!", lane->debug_name); 559 raise_luaL_error(L_, "Zombie thread %s refuses to die!", lane->debug_name);
560 } 560 }
561 } 561 }
562 562
@@ -564,22 +564,22 @@ static void selfdestruct_add(Lane* lane_)
564 if (U->timer_deep != nullptr) // test ins case some early internal error prevented Lanes from creating the deep timer 564 if (U->timer_deep != nullptr) // test ins case some early internal error prevented Lanes from creating the deep timer
565 { 565 {
566 [[maybe_unused]] int const prev_ref_count{ U->timer_deep->m_refcount.fetch_sub(1, std::memory_order_relaxed) }; 566 [[maybe_unused]] int const prev_ref_count{ U->timer_deep->m_refcount.fetch_sub(1, std::memory_order_relaxed) };
567 LUA_ASSERT(L, prev_ref_count == 1); // this should be the last reference 567 LUA_ASSERT(L_, prev_ref_count == 1); // this should be the last reference
568 DeepFactory::DeleteDeepObject(L, U->timer_deep); 568 DeepFactory::DeleteDeepObject(L_, U->timer_deep);
569 U->timer_deep = nullptr; 569 U->timer_deep = nullptr;
570 } 570 }
571 571
572 close_keepers(U); 572 close_keepers(U);
573 573
574 // remove the protected allocator, if any 574 // remove the protected allocator, if any
575 U->protected_allocator.removeFrom(L); 575 U->protected_allocator.removeFrom(L_);
576 576
577 U->Universe::~Universe(); 577 U->Universe::~Universe();
578 578
579 // universe is no longer available (nor necessary) 579 // universe is no longer available (nor necessary)
580 // we need to do this in case some deep userdata objects were created before Lanes was initialized, 580 // we need to do this in case some deep userdata objects were created before Lanes was initialized,
581 // as potentially they will be garbage collected after Lanes at application shutdown 581 // as potentially they will be garbage collected after Lanes at application shutdown
582 universe_store(L, nullptr); 582 universe_store(L_, nullptr);
583 return 0; 583 return 0;
584} 584}
585 585
@@ -593,23 +593,22 @@ static void selfdestruct_add(Lane* lane_)
593// 593//
594LUAG_FUNC( set_singlethreaded) 594LUAG_FUNC( set_singlethreaded)
595{ 595{
596 lua_Integer cores = luaL_optinteger(L, 1, 1); 596 [[maybe_unused]] lua_Integer const cores{ luaL_optinteger(L_, 1, 1) };
597 (void) cores; // prevent "unused" warning
598 597
599#ifdef PLATFORM_OSX 598#ifdef PLATFORM_OSX
600#ifdef _UTILBINDTHREADTOCPU 599#ifdef _UTILBINDTHREADTOCPU
601 if (cores > 1) 600 if (cores > 1)
602 { 601 {
603 raise_luaL_error(L, "Limiting to N>1 cores not possible"); 602 raise_luaL_error(L_, "Limiting to N>1 cores not possible");
604 } 603 }
605 // requires 'chudInitialize()' 604 // requires 'chudInitialize()'
606 utilBindThreadToCPU(0); // # of CPU to run on (we cannot limit to 2..N CPUs?) 605 utilBindThreadToCPU(0); // # of CPU to run on (we cannot limit to 2..N CPUs?)
607 return 0; 606 return 0;
608#else 607#else
609 raise_luaL_error(L, "Not available: compile with _UTILBINDTHREADTOCPU"); 608 raise_luaL_error(L_, "Not available: compile with _UTILBINDTHREADTOCPU");
610#endif 609#endif
611#else 610#else
612 raise_luaL_error(L, "not implemented"); 611 raise_luaL_error(L_, "not implemented");
613#endif 612#endif
614} 613}
615 614
@@ -638,35 +637,35 @@ static constexpr RegistryUniqueKey kExtendedStackTraceRegKey{ 0x38147AD48FB426E2
638 637
639LUAG_FUNC( set_error_reporting) 638LUAG_FUNC( set_error_reporting)
640{ 639{
641 luaL_checktype(L, 1, LUA_TSTRING); 640 luaL_checktype(L_, 1, LUA_TSTRING);
642 char const* mode{ lua_tostring(L, 1) }; 641 char const* mode{ lua_tostring(L_, 1) };
643 lua_pushliteral(L, "extended"); 642 lua_pushliteral(L_, "extended");
644 bool const extended{ strcmp(mode, "extended") == 0 }; 643 bool const extended{ strcmp(mode, "extended") == 0 };
645 bool const basic{ strcmp(mode, "basic") == 0 }; 644 bool const basic{ strcmp(mode, "basic") == 0 };
646 if (!extended && !basic) 645 if (!extended && !basic)
647 { 646 {
648 raise_luaL_error(L, "unsupported error reporting model %s", mode); 647 raise_luaL_error(L_, "unsupported error reporting model %s", mode);
649 } 648 }
650 649
651 kExtendedStackTraceRegKey.setValue(L, [extended](lua_State* L) { lua_pushboolean(L, extended ? 1 : 0); }); 650 kExtendedStackTraceRegKey.setValue(L_, [extended](lua_State* L_) { lua_pushboolean(L_, extended ? 1 : 0); });
652 return 0; 651 return 0;
653} 652}
654 653
655[[nodiscard]] static int lane_error(lua_State* L) 654[[nodiscard]] static int lane_error(lua_State* L_)
656{ 655{
657 // error message (any type) 656 // error message (any type)
658 STACK_CHECK_START_ABS(L, 1); // some_error 657 STACK_CHECK_START_ABS(L_, 1); // some_error
659 658
660 // Don't do stack survey for cancelled lanes. 659 // Don't do stack survey for cancelled lanes.
661 // 660 //
662 if (kCancelError.equals(L, 1)) 661 if (kCancelError.equals(L_, 1))
663 { 662 {
664 return 1; // just pass on 663 return 1; // just pass on
665 } 664 }
666 665
667 STACK_GROW(L, 3); 666 STACK_GROW(L_, 3);
668 bool const extended{ kExtendedStackTraceRegKey.readBoolValue(L) }; 667 bool const extended{ kExtendedStackTraceRegKey.readBoolValue(L_) };
669 STACK_CHECK(L, 1); 668 STACK_CHECK(L_, 1);
670 669
671 // Place stack trace at 'registry[kStackTraceRegKey]' for the 'lua_pcall()' 670 // Place stack trace at 'registry[kStackTraceRegKey]' for the 'lua_pcall()'
672 // caller to fetch. This bypasses the Lua 5.1 limitation of only one 671 // caller to fetch. This bypasses the Lua 5.1 limitation of only one
@@ -678,50 +677,50 @@ LUAG_FUNC( set_error_reporting)
678 // 677 //
679 // table of { "sourcefile.lua:<line>", ... } 678 // table of { "sourcefile.lua:<line>", ... }
680 // 679 //
681 lua_newtable(L); // some_error {} 680 lua_newtable(L_); // some_error {}
682 681
683 // Best to start from level 1, but in some cases it might be a C function 682 // Best to start from level 1, but in some cases it might be a C function
684 // and we don't get '.currentline' for that. It's okay - just keep level 683 // and we don't get '.currentline' for that. It's okay - just keep level
685 // and table index growing separate. --AKa 22-Jan-2009 684 // and table index growing separate. --AKa 22-Jan-2009
686 // 685 //
687 lua_Debug ar; 686 lua_Debug ar;
688 for (int n = 1; lua_getstack(L, n, &ar); ++n) 687 for (int n = 1; lua_getstack(L_, n, &ar); ++n)
689 { 688 {
690 lua_getinfo(L, extended ? "Sln" : "Sl", &ar); 689 lua_getinfo(L_, extended ? "Sln" : "Sl", &ar);
691 if (extended) 690 if (extended)
692 { 691 {
693 lua_newtable(L); // some_error {} {} 692 lua_newtable(L_); // some_error {} {}
694 693
695 lua_pushstring(L, ar.source); // some_error {} {} source 694 lua_pushstring(L_, ar.source); // some_error {} {} source
696 lua_setfield(L, -2, "source"); // some_error {} {} 695 lua_setfield(L_, -2, "source"); // some_error {} {}
697 696
698 lua_pushinteger(L, ar.currentline); // some_error {} {} currentline 697 lua_pushinteger(L_, ar.currentline); // some_error {} {} currentline
699 lua_setfield(L, -2, "currentline"); // some_error {} {} 698 lua_setfield(L_, -2, "currentline"); // some_error {} {}
700 699
701 lua_pushstring(L, ar.name); // some_error {} {} name 700 lua_pushstring(L_, ar.name); // some_error {} {} name
702 lua_setfield(L, -2, "name"); // some_error {} {} 701 lua_setfield(L_, -2, "name"); // some_error {} {}
703 702
704 lua_pushstring(L, ar.namewhat); // some_error {} {} namewhat 703 lua_pushstring(L_, ar.namewhat); // some_error {} {} namewhat
705 lua_setfield(L, -2, "namewhat"); // some_error {} {} 704 lua_setfield(L_, -2, "namewhat"); // some_error {} {}
706 705
707 lua_pushstring(L, ar.what); // some_error {} {} what 706 lua_pushstring(L_, ar.what); // some_error {} {} what
708 lua_setfield(L, -2, "what"); // some_error {} {} 707 lua_setfield(L_, -2, "what"); // some_error {} {}
709 } 708 }
710 else if (ar.currentline > 0) 709 else if (ar.currentline > 0)
711 { 710 {
712 lua_pushfstring(L, "%s:%d", ar.short_src, ar.currentline); // some_error {} "blah:blah" 711 lua_pushfstring(L_, "%s:%d", ar.short_src, ar.currentline); // some_error {} "blah:blah"
713 } 712 }
714 else 713 else
715 { 714 {
716 lua_pushfstring(L, "%s:?", ar.short_src); // some_error {} "blah" 715 lua_pushfstring(L_, "%s:?", ar.short_src); // some_error {} "blah"
717 } 716 }
718 lua_rawseti(L, -2, (lua_Integer) n); // some_error {} 717 lua_rawseti(L_, -2, (lua_Integer) n); // some_error {}
719 } 718 }
720 719
721 // store the stack trace table in the registry 720 // store the stack trace table in the registry
722 kStackTraceRegKey.setValue(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error 721 kStackTraceRegKey.setValue(L_, [](lua_State* L_) { lua_insert(L_, -2); }); // some_error
723 722
724 STACK_CHECK(L, 1); 723 STACK_CHECK(L_, 1);
725 return 1; // the untouched error value 724 return 1; // the untouched error value
726} 725}
727#endif // ERROR_FULL_STACK 726#endif // ERROR_FULL_STACK
@@ -733,19 +732,19 @@ LUAG_FUNC(set_debug_threadname)
733 // fnv164 of string "debug_threadname" generated at https://www.pelock.com/products/hash-calculator 732 // fnv164 of string "debug_threadname" generated at https://www.pelock.com/products/hash-calculator
734 constexpr RegistryUniqueKey hidden_regkey{ 0x79C0669AAAE04440ull }; 733 constexpr RegistryUniqueKey hidden_regkey{ 0x79C0669AAAE04440ull };
735 // C s_lane structure is a light userdata upvalue 734 // C s_lane structure is a light userdata upvalue
736 Lane* const lane{ lua_tolightuserdata<Lane>(L, lua_upvalueindex(1)) }; 735 Lane* const lane{ lua_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) };
737 luaL_checktype(L, -1, LUA_TSTRING); // "name" 736 luaL_checktype(L_, -1, LUA_TSTRING); // "name"
738 lua_settop(L, 1); 737 lua_settop(L_, 1);
739 STACK_CHECK_START_ABS(L, 1); 738 STACK_CHECK_START_ABS(L_, 1);
740 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... 739 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global...
741 hidden_regkey.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); 740 hidden_regkey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); });
742 STACK_CHECK(L, 1); 741 STACK_CHECK(L_, 1);
743 lane->debug_name = lua_tostring(L, -1); 742 lane->debug_name = lua_tostring(L_, -1);
744 // keep a direct pointer on the string 743 // keep a direct pointer on the string
745 THREAD_SETNAME(lane->debug_name); 744 THREAD_SETNAME(lane->debug_name);
746 // to see VM name in Decoda debugger Virtual Machine window 745 // to see VM name in Decoda debugger Virtual Machine window
747 lua_setglobal(L, "decoda_name"); // 746 lua_setglobal(L_, "decoda_name"); //
748 STACK_CHECK(L, 0); 747 STACK_CHECK(L_, 0);
749 return 0; 748 return 0;
750} 749}
751 750
@@ -753,9 +752,9 @@ LUAG_FUNC(set_debug_threadname)
753 752
754LUAG_FUNC(get_debug_threadname) 753LUAG_FUNC(get_debug_threadname)
755{ 754{
756 Lane* const lane{ ToLane(L, 1) }; 755 Lane* const lane{ ToLane(L_, 1) };
757 luaL_argcheck(L, lua_gettop(L) == 1, 2, "too many arguments"); 756 luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments");
758 lua_pushstring(L, lane->debug_name); 757 lua_pushstring(L_, lane->debug_name);
759 return 1; 758 return 1;
760} 759}
761 760
@@ -763,15 +762,15 @@ LUAG_FUNC(get_debug_threadname)
763 762
764LUAG_FUNC(set_thread_priority) 763LUAG_FUNC(set_thread_priority)
765{ 764{
766 lua_Integer const prio{ luaL_checkinteger(L, 1) }; 765 lua_Integer const prio{ luaL_checkinteger(L_, 1) };
767 // public Lanes API accepts a generic range -3/+3 766 // public Lanes API accepts a generic range -3/+3
768 // that will be remapped into the platform-specific scheduler priority scheme 767 // that will be remapped into the platform-specific scheduler priority scheme
769 // On some platforms, -3 is equivalent to -2 and +3 to +2 768 // On some platforms, -3 is equivalent to -2 and +3 to +2
770 if (prio < kThreadPrioMin || prio > kThreadPrioMax) 769 if (prio < kThreadPrioMin || prio > kThreadPrioMax)
771 { 770 {
772 raise_luaL_error(L, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, prio); 771 raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, prio);
773 } 772 }
774 THREAD_SET_PRIORITY(static_cast<int>(prio), universe_get(L)->m_sudo); 773 THREAD_SET_PRIORITY(static_cast<int>(prio), universe_get(L_)->m_sudo);
775 return 0; 774 return 0;
776} 775}
777 776
@@ -779,10 +778,10 @@ LUAG_FUNC(set_thread_priority)
779 778
780LUAG_FUNC(set_thread_affinity) 779LUAG_FUNC(set_thread_affinity)
781{ 780{
782 lua_Integer const affinity{ luaL_checkinteger(L, 1) }; 781 lua_Integer const affinity{ luaL_checkinteger(L_, 1) };
783 if (affinity <= 0) 782 if (affinity <= 0)
784 { 783 {
785 raise_luaL_error(L, "invalid affinity (%d)", affinity); 784 raise_luaL_error(L_, "invalid affinity (%d)", affinity);
786 } 785 }
787 THREAD_SET_AFFINITY( static_cast<unsigned int>(affinity)); 786 THREAD_SET_AFFINITY( static_cast<unsigned int>(affinity));
788 return 0; 787 return 0;
@@ -920,18 +919,18 @@ static void lane_main(Lane* lane)
920// upvalue[1]: _G.require 919// upvalue[1]: _G.require
921LUAG_FUNC(require) 920LUAG_FUNC(require)
922{ 921{
923 char const* name = lua_tostring(L, 1); 922 char const* name = lua_tostring(L_, 1);
924 int const nargs = lua_gettop(L); 923 int const nargs = lua_gettop(L_);
925 DEBUGSPEW_CODE(Universe* U = universe_get(L)); 924 DEBUGSPEW_CODE(Universe* U = universe_get(L_));
926 STACK_CHECK_START_REL(L, 0); 925 STACK_CHECK_START_REL(L_, 0);
927 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); 926 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name));
928 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 927 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
929 lua_pushvalue(L, lua_upvalueindex(1)); // "name" require 928 lua_pushvalue(L_, lua_upvalueindex(1)); // "name" require
930 lua_insert(L, 1); // require "name" 929 lua_insert(L_, 1); // require "name"
931 lua_call(L, nargs, 1); // module 930 lua_call(L_, nargs, 1); // module
932 populate_func_lookup_table(L, -1, name); 931 populate_func_lookup_table(L_, -1, name);
933 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); 932 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name));
934 STACK_CHECK(L, 0); 933 STACK_CHECK(L_, 0);
935 return 1; 934 return 1;
936} 935}
937 936
@@ -942,18 +941,18 @@ LUAG_FUNC(require)
942// lanes.register( "modname", module) 941// lanes.register( "modname", module)
943LUAG_FUNC(register) 942LUAG_FUNC(register)
944{ 943{
945 char const* name = luaL_checkstring(L, 1); 944 char const* name = luaL_checkstring(L_, 1);
946 LuaType const mod_type{ lua_type_as_enum(L, 2) }; 945 LuaType const mod_type{ lua_type_as_enum(L_, 2) };
947 // ignore extra parameters, just in case 946 // ignore extra parameters, just in case
948 lua_settop(L, 2); 947 lua_settop(L_, 2);
949 luaL_argcheck(L, (mod_type == LuaType::TABLE) || (mod_type == LuaType::FUNCTION), 2, "unexpected module type"); 948 luaL_argcheck(L_, (mod_type == LuaType::TABLE) || (mod_type == LuaType::FUNCTION), 2, "unexpected module type");
950 DEBUGSPEW_CODE(Universe* U = universe_get(L)); 949 DEBUGSPEW_CODE(Universe* U = universe_get(L));
951 STACK_CHECK_START_REL(L, 0); // "name" mod_table 950 STACK_CHECK_START_REL(L_, 0); // "name" mod_table
952 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); 951 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name));
953 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 952 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
954 populate_func_lookup_table(L, -1, name); 953 populate_func_lookup_table(L_, -1, name);
955 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); 954 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name));
956 STACK_CHECK(L, 0); 955 STACK_CHECK(L_, 0);
957 return 0; 956 return 0;
958} 957}
959 958
@@ -976,38 +975,38 @@ static constexpr UniqueKey kLaneGC{ 0x5D6122141727F960ull };
976// 975//
977LUAG_FUNC(lane_new) 976LUAG_FUNC(lane_new)
978{ 977{
979 char const* const libs_str{ lua_tostring(L, 2) }; 978 char const* const libs_str{ lua_tostring(L_, 2) };
980 bool const have_priority{ !lua_isnoneornil(L, 3) }; 979 bool const have_priority{ !lua_isnoneornil(L_, 3) };
981 int const priority{ have_priority ? (int) lua_tointeger(L, 3) : kThreadPrioDefault }; 980 int const priority{ have_priority ? static_cast<int>(lua_tointeger(L_, 3)) : kThreadPrioDefault };
982 int const globals_idx{ lua_isnoneornil(L, 4) ? 0 : 4 }; 981 int const globals_idx{ lua_isnoneornil(L_, 4) ? 0 : 4 };
983 int const package_idx{ lua_isnoneornil(L, 5) ? 0 : 5 }; 982 int const package_idx{ lua_isnoneornil(L_, 5) ? 0 : 5 };
984 int const required_idx{ lua_isnoneornil(L, 6) ? 0 : 6 }; 983 int const required_idx{ lua_isnoneornil(L_, 6) ? 0 : 6 };
985 int const gc_cb_idx{ lua_isnoneornil(L, 7) ? 0 : 7 }; 984 int const gc_cb_idx{ lua_isnoneornil(L_, 7) ? 0 : 7 };
986 985
987 static constexpr int kFixedArgsIdx{ 7 }; 986 static constexpr int kFixedArgsIdx{ 7 };
988 int const nargs{ lua_gettop(L) - kFixedArgsIdx }; 987 int const nargs{ lua_gettop(L_) - kFixedArgsIdx };
989 Universe* const U{ universe_get(L) }; 988 Universe* const U{ universe_get(L_) };
990 LUA_ASSERT(L, nargs >= 0); 989 LUA_ASSERT(L_, nargs >= 0);
991 990
992 // public Lanes API accepts a generic range -3/+3 991 // public Lanes API accepts a generic range -3/+3
993 // that will be remapped into the platform-specific scheduler priority scheme 992 // that will be remapped into the platform-specific scheduler priority scheme
994 // On some platforms, -3 is equivalent to -2 and +3 to +2 993 // On some platforms, -3 is equivalent to -2 and +3 to +2
995 if (have_priority && (priority < kThreadPrioMin || priority > kThreadPrioMax)) 994 if (have_priority && (priority < kThreadPrioMin || priority > kThreadPrioMax))
996 { 995 {
997 raise_luaL_error(L, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, priority); 996 raise_luaL_error(L_, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, priority);
998 } 997 }
999 998
1000 /* --- Create and prepare the sub state --- */ 999 /* --- Create and prepare the sub state --- */
1001 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END)); 1000 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END));
1002 1001
1003 // populate with selected libraries at the same time 1002 // populate with selected libraries at the same time
1004 lua_State* const L2{ luaG_newstate(U, SourceState{ L }, libs_str) }; // L // L2 1003 lua_State* const L2{ luaG_newstate(U, SourceState{ L_ }, libs_str) }; // L // L2
1005 1004
1006 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) 1005 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread)
1007 Lane* const lane{ new (U) Lane{ U, L2 } }; 1006 Lane* const lane{ new (U) Lane{ U, L2 } };
1008 if (lane == nullptr) 1007 if (lane == nullptr)
1009 { 1008 {
1010 raise_luaL_error(L, "could not create lane: out of memory"); 1009 raise_luaL_error(L_, "could not create lane: out of memory");
1011 } 1010 }
1012 1011
1013 class OnExit 1012 class OnExit
@@ -1090,7 +1089,7 @@ LUAG_FUNC(lane_new)
1090 m_lane->m_ready.count_down(); 1089 m_lane->m_ready.count_down();
1091 m_lane = nullptr; 1090 m_lane = nullptr;
1092 } 1091 }
1093 } onExit{ L, lane, gc_cb_idx DEBUGSPEW_COMMA_PARAM(U) }; 1092 } onExit{ L_, lane, gc_cb_idx DEBUGSPEW_COMMA_PARAM(U) };
1094 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation 1093 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation
1095 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); 1094 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END));
1096 lane->startThread(priority); 1095 lane->startThread(priority);
@@ -1098,22 +1097,22 @@ LUAG_FUNC(lane_new)
1098 STACK_GROW( L2, nargs + 3); // 1097 STACK_GROW( L2, nargs + 3); //
1099 STACK_CHECK_START_REL(L2, 0); 1098 STACK_CHECK_START_REL(L2, 0);
1100 1099
1101 STACK_GROW(L, 3); // func libs priority globals package required gc_cb [... args ...] 1100 STACK_GROW(L_, 3); // func libs priority globals package required gc_cb [... args ...]
1102 STACK_CHECK_START_REL(L, 0); 1101 STACK_CHECK_START_REL(L_, 0);
1103 1102
1104 // give a default "Lua" name to the thread to see VM name in Decoda debugger 1103 // give a default "Lua" name to the thread to see VM name in Decoda debugger
1105 lua_pushfstring( L2, "Lane #%p", L2); // "..." 1104 lua_pushfstring( L2, "Lane #%p", L2); // "..."
1106 lua_setglobal( L2, "decoda_name"); // 1105 lua_setglobal( L2, "decoda_name"); //
1107 LUA_ASSERT(L, lua_gettop( L2) == 0); 1106 LUA_ASSERT(L_, lua_gettop( L2) == 0);
1108 1107
1109 // package 1108 // package
1110 if (package_idx != 0) 1109 if (package_idx != 0)
1111 { 1110 {
1112 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END)); 1111 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END));
1113 // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack 1112 // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack
1114 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L }, {}, SourceIndex{ package_idx }, {}, {}, {} }; 1113 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L_ }, {}, SourceIndex{ package_idx }, {}, {}, {} };
1115 [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() }; 1114 [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() };
1116 LUA_ASSERT(L, ret == InterCopyResult::Success); // either all went well, or we should not even get here 1115 LUA_ASSERT(L_, ret == InterCopyResult::Success); // either all went well, or we should not even get here
1117 } 1116 }
1118 1117
1119 // modules to require in the target lane *before* the function is transfered! 1118 // modules to require in the target lane *before* the function is transfered!
@@ -1123,23 +1122,23 @@ LUAG_FUNC(lane_new)
1123 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END)); 1122 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END));
1124 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 1123 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
1125 // should not happen, was checked in lanes.lua before calling lane_new() 1124 // should not happen, was checked in lanes.lua before calling lane_new()
1126 if (lua_type(L, required_idx) != LUA_TTABLE) 1125 if (lua_type(L_, required_idx) != LUA_TTABLE)
1127 { 1126 {
1128 raise_luaL_error(L, "expected required module list as a table, got %s", luaL_typename(L, required_idx)); 1127 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, required_idx));
1129 } 1128 }
1130 1129
1131 lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil 1130 lua_pushnil(L_); // func libs priority globals package required gc_cb [... args ...] nil
1132 while (lua_next(L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname" 1131 while (lua_next(L_, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname"
1133 { 1132 {
1134 if (lua_type(L, -1) != LUA_TSTRING || lua_type(L, -2) != LUA_TNUMBER || lua_tonumber(L, -2) != nbRequired) 1133 if (lua_type(L_, -1) != LUA_TSTRING || lua_type(L_, -2) != LUA_TNUMBER || lua_tonumber(L_, -2) != nbRequired)
1135 { 1134 {
1136 raise_luaL_error(L, "required module list should be a list of strings"); 1135 raise_luaL_error(L_, "required module list should be a list of strings");
1137 } 1136 }
1138 else 1137 else
1139 { 1138 {
1140 // require the module in the target state, and populate the lookup table there too 1139 // require the module in the target state, and populate the lookup table there too
1141 size_t len; 1140 size_t len;
1142 char const* name = lua_tolstring(L, -1, &len); 1141 char const* name = lua_tolstring(L_, -1, &len);
1143 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name)); 1142 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name));
1144 1143
1145 // require the module in the target lane 1144 // require the module in the target lane
@@ -1147,7 +1146,7 @@ LUAG_FUNC(lane_new)
1147 if (lua_isnil( L2, -1)) 1146 if (lua_isnil( L2, -1))
1148 { 1147 {
1149 lua_pop( L2, 1); // 1148 lua_pop( L2, 1); //
1150 raise_luaL_error(L, "cannot pre-require modules without loading 'package' library first"); 1149 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first");
1151 } 1150 }
1152 else 1151 else
1153 { 1152 {
@@ -1155,20 +1154,20 @@ LUAG_FUNC(lane_new)
1155 if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode 1154 if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode
1156 { 1155 {
1157 // propagate error to main state if any 1156 // propagate error to main state if any
1158 InterCopyContext c{ U, DestState{ L }, SourceState{ L2 }, {}, {}, {}, {}, {} }; 1157 InterCopyContext c{ U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} };
1159 std::ignore = c.inter_move(1); // func libs priority globals package required gc_cb [... args ...] n "modname" error 1158 std::ignore = c.inter_move(1); // func libs priority globals package required gc_cb [... args ...] n "modname" error
1160 raise_lua_error(L); 1159 raise_lua_error(L_);
1161 } 1160 }
1162 // after requiring the module, register the functions it exported in our name<->function database 1161 // after requiring the module, register the functions it exported in our name<->function database
1163 populate_func_lookup_table( L2, -1, name); 1162 populate_func_lookup_table( L2, -1, name);
1164 lua_pop( L2, 1); // 1163 lua_pop( L2, 1); //
1165 } 1164 }
1166 } 1165 }
1167 lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n 1166 lua_pop(L_, 1); // func libs priority globals package required gc_cb [... args ...] n
1168 ++ nbRequired; 1167 ++ nbRequired;
1169 } // func libs priority globals package required gc_cb [... args ...] 1168 } // func libs priority globals package required gc_cb [... args ...]
1170 } 1169 }
1171 STACK_CHECK(L, 0); 1170 STACK_CHECK(L_, 0);
1172 STACK_CHECK(L2, 0); // 1171 STACK_CHECK(L2, 0); //
1173 1172
1174 // Appending the specified globals to the global environment 1173 // Appending the specified globals to the global environment
@@ -1177,83 +1176,83 @@ LUAG_FUNC(lane_new)
1177 if (globals_idx != 0) 1176 if (globals_idx != 0)
1178 { 1177 {
1179 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END)); 1178 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END));
1180 if (!lua_istable(L, globals_idx)) 1179 if (!lua_istable(L_, globals_idx))
1181 { 1180 {
1182 raise_luaL_error(L, "Expected table, got %s", luaL_typename(L, globals_idx)); 1181 raise_luaL_error(L_, "Expected table, got %s", luaL_typename(L_, globals_idx));
1183 } 1182 }
1184 1183
1185 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 1184 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
1186 lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil 1185 lua_pushnil(L_); // func libs priority globals package required gc_cb [... args ...] nil
1187 // Lua 5.2 wants us to push the globals table on the stack 1186 // Lua 5.2 wants us to push the globals table on the stack
1188 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L }, {}, {}, {}, {}, {} }; 1187 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
1189 lua_pushglobaltable(L2); // _G 1188 lua_pushglobaltable(L2); // _G
1190 while( lua_next(L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v 1189 while( lua_next(L_, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v
1191 { 1190 {
1192 std::ignore = c.inter_copy(2); // _G k v 1191 std::ignore = c.inter_copy(2); // _G k v
1193 // assign it in L2's globals table 1192 // assign it in L2's globals table
1194 lua_rawset(L2, -3); // _G 1193 lua_rawset(L2, -3); // _G
1195 lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] k 1194 lua_pop(L_, 1); // func libs priority globals package required gc_cb [... args ...] k
1196 } // func libs priority globals package required gc_cb [... args ...] 1195 } // func libs priority globals package required gc_cb [... args ...]
1197 lua_pop( L2, 1); // 1196 lua_pop( L2, 1); //
1198 } 1197 }
1199 STACK_CHECK(L, 0); 1198 STACK_CHECK(L_, 0);
1200 STACK_CHECK(L2, 0); 1199 STACK_CHECK(L2, 0);
1201 1200
1202 // Lane main function 1201 // Lane main function
1203 LuaType const func_type{ lua_type_as_enum(L, 1) }; 1202 LuaType const func_type{ lua_type_as_enum(L_, 1) };
1204 if (func_type == LuaType::FUNCTION) 1203 if (func_type == LuaType::FUNCTION)
1205 { 1204 {
1206 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); 1205 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END));
1207 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 1206 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
1208 lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func 1207 lua_pushvalue(L_, 1); // func libs priority globals package required gc_cb [... args ...] func
1209 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L }, {}, {}, {}, {}, {} }; 1208 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
1210 InterCopyResult const res{ c.inter_move(1) }; // func libs priority globals package required gc_cb [... args ...] // func 1209 InterCopyResult const res{ c.inter_move(1) }; // func libs priority globals package required gc_cb [... args ...] // func
1211 if (res != InterCopyResult::Success) 1210 if (res != InterCopyResult::Success)
1212 { 1211 {
1213 raise_luaL_error(L, "tried to copy unsupported types"); 1212 raise_luaL_error(L_, "tried to copy unsupported types");
1214 } 1213 }
1215 } 1214 }
1216 else if (func_type == LuaType::STRING) 1215 else if (func_type == LuaType::STRING)
1217 { 1216 {
1218 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END)); 1217 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END));
1219 // compile the string 1218 // compile the string
1220 if (luaL_loadstring(L2, lua_tostring(L, 1)) != 0) // func 1219 if (luaL_loadstring(L2, lua_tostring(L_, 1)) != 0) // func
1221 { 1220 {
1222 raise_luaL_error(L, "error when parsing lane function code"); 1221 raise_luaL_error(L_, "error when parsing lane function code");
1223 } 1222 }
1224 } 1223 }
1225 else 1224 else
1226 { 1225 {
1227 raise_luaL_error(L, "Expected function, got %s", lua_typename(L, func_type)); 1226 raise_luaL_error(L_, "Expected function, got %s", lua_typename(L_, func_type));
1228 } 1227 }
1229 STACK_CHECK(L, 0); 1228 STACK_CHECK(L_, 0);
1230 STACK_CHECK(L2, 1); 1229 STACK_CHECK(L2, 1);
1231 LUA_ASSERT(L, lua_isfunction(L2, 1)); 1230 LUA_ASSERT(L_, lua_isfunction(L2, 1));
1232 1231
1233 // revive arguments 1232 // revive arguments
1234 if (nargs > 0) 1233 if (nargs > 0)
1235 { 1234 {
1236 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); 1235 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END));
1237 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 1236 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
1238 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L }, {}, {}, {}, {}, {} }; 1237 InterCopyContext c{ U, DestState{ L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
1239 InterCopyResult const res{ c.inter_move(nargs) }; // func libs priority globals package required gc_cb // func [... args ...] 1238 InterCopyResult const res{ c.inter_move(nargs) }; // func libs priority globals package required gc_cb // func [... args ...]
1240 if (res != InterCopyResult::Success) 1239 if (res != InterCopyResult::Success)
1241 { 1240 {
1242 raise_luaL_error(L, "tried to copy unsupported types"); 1241 raise_luaL_error(L_, "tried to copy unsupported types");
1243 } 1242 }
1244 } 1243 }
1245 STACK_CHECK(L, -nargs); 1244 STACK_CHECK(L_, -nargs);
1246 LUA_ASSERT(L, lua_gettop(L) == kFixedArgsIdx); 1245 LUA_ASSERT(L_, lua_gettop(L_) == kFixedArgsIdx);
1247 1246
1248 // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). 1247 // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive).
1249 kLanePointerRegKey.setValue(L2, [lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); }); // func [... args ...] 1248 kLanePointerRegKey.setValue(L2, [lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); }); // func [... args ...]
1250 STACK_CHECK(L2, 1 + nargs); 1249 STACK_CHECK(L2, 1 + nargs);
1251 1250
1252 STACK_CHECK_RESET_REL(L, 0); 1251 STACK_CHECK_RESET_REL(L_, 0);
1253 // all went well, the lane's thread can start working 1252 // all went well, the lane's thread can start working
1254 onExit.success(); 1253 onExit.success();
1255 // we should have the lane userdata on top of the stack 1254 // we should have the lane userdata on top of the stack
1256 STACK_CHECK(L, 1); 1255 STACK_CHECK(L_, 1);
1257 return 1; 1256 return 1;
1258} 1257}
1259 1258
@@ -1271,24 +1270,24 @@ LUAG_FUNC(lane_new)
1271// and the issue of canceling/killing threads at gc is not very nice, either 1270// and the issue of canceling/killing threads at gc is not very nice, either
1272// (would easily cause waits at gc cycle, which we don't want). 1271// (would easily cause waits at gc cycle, which we don't want).
1273// 1272//
1274[[nodiscard]] static int lane_gc(lua_State* L) 1273[[nodiscard]] static int lane_gc(lua_State* L_)
1275{ 1274{
1276 bool have_gc_cb{ false }; 1275 bool have_gc_cb{ false };
1277 Lane* const lane{ ToLane(L, 1) }; // ud 1276 Lane* const lane{ ToLane(L_, 1) }; // ud
1278 1277
1279 // if there a gc callback? 1278 // if there a gc callback?
1280 lua_getiuservalue(L, 1, 1); // ud uservalue 1279 lua_getiuservalue(L_, 1, 1); // ud uservalue
1281 kLaneGC.pushKey(L); // ud uservalue __gc 1280 kLaneGC.pushKey(L_); // ud uservalue __gc
1282 lua_rawget(L, -2); // ud uservalue gc_cb|nil 1281 lua_rawget(L_, -2); // ud uservalue gc_cb|nil
1283 if (!lua_isnil(L, -1)) 1282 if (!lua_isnil(L_, -1))
1284 { 1283 {
1285 lua_remove(L, -2); // ud gc_cb|nil 1284 lua_remove(L_, -2); // ud gc_cb|nil
1286 lua_pushstring(L, lane->debug_name); // ud gc_cb name 1285 lua_pushstring(L_, lane->debug_name); // ud gc_cb name
1287 have_gc_cb = true; 1286 have_gc_cb = true;
1288 } 1287 }
1289 else 1288 else
1290 { 1289 {
1291 lua_pop(L, 2); // ud 1290 lua_pop(L_, 2); // ud
1292 } 1291 }
1293 1292
1294 // We can read 'lane->status' without locks, but not wait for it 1293 // We can read 'lane->status' without locks, but not wait for it
@@ -1299,8 +1298,8 @@ LUAG_FUNC(lane_new)
1299 assert(lane->selfdestruct_next); 1298 assert(lane->selfdestruct_next);
1300 if (have_gc_cb) 1299 if (have_gc_cb)
1301 { 1300 {
1302 lua_pushliteral(L, "selfdestruct"); // ud gc_cb name status 1301 lua_pushliteral(L_, "selfdestruct"); // ud gc_cb name status
1303 lua_call(L, 2, 0); // ud 1302 lua_call(L_, 2, 0); // ud
1304 } 1303 }
1305 return 0; 1304 return 0;
1306 } 1305 }
@@ -1319,8 +1318,8 @@ LUAG_FUNC(lane_new)
1319 // do this after lane cleanup in case the callback triggers an error 1318 // do this after lane cleanup in case the callback triggers an error
1320 if (have_gc_cb) 1319 if (have_gc_cb)
1321 { 1320 {
1322 lua_pushliteral(L, "closed"); // ud gc_cb name status 1321 lua_pushliteral(L_, "closed"); // ud gc_cb name status
1323 lua_call(L, 2, 0); // ud 1322 lua_call(L_, 2, 0); // ud
1324 } 1323 }
1325 return 0; 1324 return 0;
1326} 1325}
@@ -1374,27 +1373,27 @@ void Lane::pushThreadStatus(lua_State* L_)
1374// 1373//
1375LUAG_FUNC(thread_join) 1374LUAG_FUNC(thread_join)
1376{ 1375{
1377 Lane* const lane{ ToLane(L, 1) }; 1376 Lane* const lane{ ToLane(L_, 1) };
1378 lua_Duration const duration{ luaL_optnumber(L, 2, -1.0) }; 1377 lua_Duration const duration{ luaL_optnumber(L_, 2, -1.0) };
1379 lua_State* const L2{ lane->L }; 1378 lua_State* const L2{ lane->L };
1380 1379
1381 bool const done{ !lane->m_thread.joinable() || lane->waitForCompletion(duration) }; 1380 bool const done{ !lane->m_thread.joinable() || lane->waitForCompletion(duration) };
1382 if (!done || !L2) 1381 if (!done || !L2)
1383 { 1382 {
1384 STACK_GROW(L, 2); 1383 STACK_GROW(L_, 2);
1385 lua_pushnil(L); 1384 lua_pushnil(L_);
1386 lua_pushliteral(L, "timeout"); 1385 lua_pushliteral(L_, "timeout");
1387 return 2; 1386 return 2;
1388 } 1387 }
1389 1388
1390 STACK_CHECK_START_REL(L, 0); 1389 STACK_CHECK_START_REL(L_, 0);
1391 // Thread is Done/Error/Cancelled; all ours now 1390 // Thread is Done/Error/Cancelled; all ours now
1392 1391
1393 int ret{ 0 }; 1392 int ret{ 0 };
1394 Universe* const U{ lane->U }; 1393 Universe* const U{ lane->U };
1395 // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed 1394 // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed
1396 // so store it in the userdata uservalue at a key that can't possibly collide 1395 // so store it in the userdata uservalue at a key that can't possibly collide
1397 securize_debug_threadname(L, lane); 1396 securize_debug_threadname(L_, lane);
1398 switch (lane->m_status) 1397 switch (lane->m_status)
1399 { 1398 {
1400 case Lane::Done: 1399 case Lane::Done:
@@ -1402,10 +1401,10 @@ LUAG_FUNC(thread_join)
1402 int const n{ lua_gettop(L2) }; // whole L2 stack 1401 int const n{ lua_gettop(L2) }; // whole L2 stack
1403 if ( 1402 if (
1404 (n > 0) && 1403 (n > 0) &&
1405 (InterCopyContext{ U, DestState{ L }, SourceState{ L2 }, {}, {}, {}, {}, {} }.inter_move(n) != InterCopyResult::Success) 1404 (InterCopyContext{ U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} }.inter_move(n) != InterCopyResult::Success)
1406 ) 1405 )
1407 { 1406 {
1408 raise_luaL_error(L, "tried to copy unsupported types"); 1407 raise_luaL_error(L_, "tried to copy unsupported types");
1409 } 1408 }
1410 ret = n; 1409 ret = n;
1411 } 1410 }
@@ -1414,13 +1413,13 @@ LUAG_FUNC(thread_join)
1414 case Lane::Error: 1413 case Lane::Error:
1415 { 1414 {
1416 int const n{ lua_gettop(L2) }; 1415 int const n{ lua_gettop(L2) };
1417 STACK_GROW(L, 3); 1416 STACK_GROW(L_, 3);
1418 lua_pushnil(L); 1417 lua_pushnil(L_);
1419 // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... 1418 // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ...
1420 InterCopyContext c{ U, DestState{ L }, SourceState{ L2 }, {}, {}, {}, {}, {} }; 1419 InterCopyContext c{ U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} };
1421 if (c.inter_move(n) != InterCopyResult::Success) // nil "err" [trace] 1420 if (c.inter_move(n) != InterCopyResult::Success) // nil "err" [trace]
1422 { 1421 {
1423 raise_luaL_error(L, "tried to copy unsupported types: %s", lua_tostring(L, -n)); 1422 raise_luaL_error(L_, "tried to copy unsupported types: %s", lua_tostring(L_, -n));
1424 } 1423 }
1425 ret = 1 + n; 1424 ret = 1 + n;
1426 } 1425 }
@@ -1432,12 +1431,12 @@ LUAG_FUNC(thread_join)
1432 1431
1433 default: 1432 default:
1434 DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", lane->m_status)); 1433 DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", lane->m_status));
1435 LUA_ASSERT(L, false); 1434 LUA_ASSERT(L_, false);
1436 ret = 0; 1435 ret = 0;
1437 } 1436 }
1438 lua_close(L2); 1437 lua_close(L2);
1439 lane->L = nullptr; 1438 lane->L = nullptr;
1440 STACK_CHECK(L, ret); 1439 STACK_CHECK(L_, ret);
1441 return ret; 1440 return ret;
1442} 1441}
1443 1442
@@ -1454,60 +1453,60 @@ LUAG_FUNC(thread_index)
1454{ 1453{
1455 static constexpr int kSelf{ 1 }; 1454 static constexpr int kSelf{ 1 };
1456 static constexpr int kKey{ 2 }; 1455 static constexpr int kKey{ 2 };
1457 Lane* const lane{ ToLane(L, kSelf) }; 1456 Lane* const lane{ ToLane(L_, kSelf) };
1458 LUA_ASSERT(L, lua_gettop(L) == 2); 1457 LUA_ASSERT(L_, lua_gettop(L_) == 2);
1459 1458
1460 STACK_GROW(L, 8); // up to 8 positions are needed in case of error propagation 1459 STACK_GROW(L_, 8); // up to 8 positions are needed in case of error propagation
1461 1460
1462 // If key is numeric, wait until the thread returns and populate the environment with the return values 1461 // If key is numeric, wait until the thread returns and populate the environment with the return values
1463 if (lua_type(L, kKey) == LUA_TNUMBER) 1462 if (lua_type(L_, kKey) == LUA_TNUMBER)
1464 { 1463 {
1465 static constexpr int kUsr{ 3 }; 1464 static constexpr int kUsr{ 3 };
1466 // first, check that we don't already have an environment that holds the requested value 1465 // first, check that we don't already have an environment that holds the requested value
1467 { 1466 {
1468 // If key is found in the uservalue, return it 1467 // If key is found in the uservalue, return it
1469 lua_getiuservalue(L, kSelf, 1); 1468 lua_getiuservalue(L_, kSelf, 1);
1470 lua_pushvalue(L, kKey); 1469 lua_pushvalue(L_, kKey);
1471 lua_rawget(L, kUsr); 1470 lua_rawget(L_, kUsr);
1472 if (!lua_isnil(L, -1)) 1471 if (!lua_isnil(L_, -1))
1473 { 1472 {
1474 return 1; 1473 return 1;
1475 } 1474 }
1476 lua_pop(L, 1); 1475 lua_pop(L_, 1);
1477 } 1476 }
1478 { 1477 {
1479 // check if we already fetched the values from the thread or not 1478 // check if we already fetched the values from the thread or not
1480 lua_pushinteger(L, 0); 1479 lua_pushinteger(L_, 0);
1481 lua_rawget(L, kUsr); 1480 lua_rawget(L_, kUsr);
1482 bool const fetched{ !lua_isnil(L, -1) }; 1481 bool const fetched{ !lua_isnil(L_, -1) };
1483 lua_pop(L, 1); // back to our 2 args + uservalue on the stack 1482 lua_pop(L_, 1); // back to our 2 args + uservalue on the stack
1484 if (!fetched) 1483 if (!fetched)
1485 { 1484 {
1486 lua_pushinteger(L, 0); 1485 lua_pushinteger(L_, 0);
1487 lua_pushboolean(L, 1); 1486 lua_pushboolean(L_, 1);
1488 lua_rawset(L, kUsr); 1487 lua_rawset(L_, kUsr);
1489 // wait until thread has completed 1488 // wait until thread has completed
1490 lua_pushcfunction(L, LG_thread_join); 1489 lua_pushcfunction(L_, LG_thread_join);
1491 lua_pushvalue(L, kSelf); 1490 lua_pushvalue(L_, kSelf);
1492 lua_call(L, 1, LUA_MULTRET); // all return values are on the stack, at slots 4+ 1491 lua_call(L_, 1, LUA_MULTRET); // all return values are on the stack, at slots 4+
1493 switch (lane->m_status) 1492 switch (lane->m_status)
1494 { 1493 {
1495 default: 1494 default:
1496 // this is an internal error, we probably never get here 1495 // this is an internal error, we probably never get here
1497 lua_settop(L, 0); 1496 lua_settop(L_, 0);
1498 lua_pushliteral(L, "Unexpected status: "); 1497 lua_pushliteral(L_, "Unexpected status: ");
1499 lua_pushstring(L, thread_status_string(lane->m_status)); 1498 lua_pushstring(L_, thread_status_string(lane->m_status));
1500 lua_concat(L, 2); 1499 lua_concat(L_, 2);
1501 raise_lua_error(L); 1500 raise_lua_error(L_);
1502 [[fallthrough]]; // fall through if we are killed, as we got nil, "killed" on the stack 1501 [[fallthrough]]; // fall through if we are killed, as we got nil, "killed" on the stack
1503 1502
1504 case Lane::Done: // got regular return values 1503 case Lane::Done: // got regular return values
1505 { 1504 {
1506 int const nvalues{ lua_gettop(L) - 3 }; 1505 int const nvalues{ lua_gettop(L_) - 3 };
1507 for (int i = nvalues; i > 0; --i) 1506 for (int i = nvalues; i > 0; --i)
1508 { 1507 {
1509 // pop the last element of the stack, to store it in the uservalue at its proper index 1508 // pop the last element of the stack, to store it in the uservalue at its proper index
1510 lua_rawseti(L, kUsr, i); 1509 lua_rawseti(L_, kUsr, i);
1511 } 1510 }
1512 } 1511 }
1513 break; 1512 break;
@@ -1516,11 +1515,11 @@ LUAG_FUNC(thread_index)
1516 // me[-2] could carry the stack table, but even 1515 // me[-2] could carry the stack table, but even
1517 // me[-1] is rather unnecessary (and undocumented); 1516 // me[-1] is rather unnecessary (and undocumented);
1518 // use ':join()' instead. --AKa 22-Jan-2009 1517 // use ':join()' instead. --AKa 22-Jan-2009
1519 LUA_ASSERT(L, lua_isnil(L, 4) && !lua_isnil(L, 5) && lua_istable(L, 6)); 1518 LUA_ASSERT(L_, lua_isnil(L_, 4) && !lua_isnil(L_, 5) && lua_istable(L_, 6));
1520 // store errstring at key -1 1519 // store errstring at key -1
1521 lua_pushnumber(L, -1); 1520 lua_pushnumber(L_, -1);
1522 lua_pushvalue(L, 5); 1521 lua_pushvalue(L_, 5);
1523 lua_rawset(L, kUsr); 1522 lua_rawset(L_, kUsr);
1524 break; 1523 break;
1525 1524
1526 case Lane::Cancelled: 1525 case Lane::Cancelled:
@@ -1528,13 +1527,13 @@ LUAG_FUNC(thread_index)
1528 break; 1527 break;
1529 } 1528 }
1530 } 1529 }
1531 lua_settop(L, 3); // self KEY ENV 1530 lua_settop(L_, 3); // self KEY ENV
1532 int const key{ static_cast<int>(lua_tointeger(L, kKey)) }; 1531 int const key{ static_cast<int>(lua_tointeger(L_, kKey)) };
1533 if (key != -1) 1532 if (key != -1)
1534 { 1533 {
1535 lua_pushnumber(L, -1); // self KEY ENV -1 1534 lua_pushnumber(L_, -1); // self KEY ENV -1
1536 lua_rawget(L, kUsr); // self KEY ENV "error"|nil 1535 lua_rawget(L_, kUsr); // self KEY ENV "error"|nil
1537 if (!lua_isnil(L, -1)) // an error was stored 1536 if (!lua_isnil(L_, -1)) // an error was stored
1538 { 1537 {
1539 // Note: Lua 5.1 interpreter is not prepared to show 1538 // Note: Lua 5.1 interpreter is not prepared to show
1540 // non-string errors, so we use 'tostring()' here 1539 // non-string errors, so we use 'tostring()' here
@@ -1547,50 +1546,50 @@ LUAG_FUNC(thread_index)
1547 // Level 3 should show the line where 'h[x]' was read 1546 // Level 3 should show the line where 'h[x]' was read
1548 // but this only seems to work for string messages 1547 // but this only seems to work for string messages
1549 // (Lua 5.1.4). No idea, why. --AKa 22-Jan-2009 1548 // (Lua 5.1.4). No idea, why. --AKa 22-Jan-2009
1550 lua_getmetatable(L, kSelf); // self KEY ENV "error" mt 1549 lua_getmetatable(L_, kSelf); // self KEY ENV "error" mt
1551 lua_getfield(L, -1, "cached_error"); // self KEY ENV "error" mt error() 1550 lua_getfield(L_, -1, "cached_error"); // self KEY ENV "error" mt error()
1552 lua_getfield(L, -2, "cached_tostring"); // self KEY ENV "error" mt error() tostring() 1551 lua_getfield(L_, -2, "cached_tostring"); // self KEY ENV "error" mt error() tostring()
1553 lua_pushvalue(L, 4); // self KEY ENV "error" mt error() tostring() "error" 1552 lua_pushvalue(L_, 4); // self KEY ENV "error" mt error() tostring() "error"
1554 lua_call(L, 1, 1); // tostring( errstring) -- just in case // self KEY ENV "error" mt error() "error" 1553 lua_call(L_, 1, 1); // tostring( errstring) -- just in case // self KEY ENV "error" mt error() "error"
1555 lua_pushinteger(L, 3); // self KEY ENV "error" mt error() "error" 3 1554 lua_pushinteger(L_, 3); // self KEY ENV "error" mt error() "error" 3
1556 lua_call(L, 2, 0); // error( tostring( errstring), 3) // self KEY ENV "error" mt 1555 lua_call(L_, 2, 0); // error( tostring( errstring), 3) // self KEY ENV "error" mt
1557 } 1556 }
1558 else 1557 else
1559 { 1558 {
1560 lua_pop(L, 1); // self KEY ENV 1559 lua_pop(L_, 1); // self KEY ENV
1561 } 1560 }
1562 } 1561 }
1563 lua_rawgeti(L, kUsr, key); 1562 lua_rawgeti(L_, kUsr, key);
1564 } 1563 }
1565 return 1; 1564 return 1;
1566 } 1565 }
1567 if (lua_type(L, kKey) == LUA_TSTRING) 1566 if (lua_type(L_, kKey) == LUA_TSTRING)
1568 { 1567 {
1569 char const* const keystr{ lua_tostring(L, kKey) }; 1568 char const* const keystr{ lua_tostring(L_, kKey) };
1570 lua_settop(L, 2); // keep only our original arguments on the stack 1569 lua_settop(L_, 2); // keep only our original arguments on the stack
1571 if (strcmp( keystr, "status") == 0) 1570 if (strcmp( keystr, "status") == 0)
1572 { 1571 {
1573 lane->pushThreadStatus(L); // push the string representing the status 1572 lane->pushThreadStatus(L_); // push the string representing the status
1574 return 1; 1573 return 1;
1575 } 1574 }
1576 // return self.metatable[key] 1575 // return self.metatable[key]
1577 lua_getmetatable(L, kSelf); // self KEY mt 1576 lua_getmetatable(L_, kSelf); // self KEY mt
1578 lua_replace(L, -3); // mt KEY 1577 lua_replace(L_, -3); // mt KEY
1579 lua_rawget(L, -2); // mt value 1578 lua_rawget(L_, -2); // mt value
1580 // only "cancel" and "join" are registered as functions, any other string will raise an error 1579 // only "cancel" and "join" are registered as functions, any other string will raise an error
1581 if (!lua_iscfunction(L, -1)) 1580 if (!lua_iscfunction(L_, -1))
1582 { 1581 {
1583 raise_luaL_error(L, "can't index a lane with '%s'", keystr); 1582 raise_luaL_error(L_, "can't index a lane with '%s'", keystr);
1584 } 1583 }
1585 return 1; 1584 return 1;
1586 } 1585 }
1587 // unknown key 1586 // unknown key
1588 lua_getmetatable(L, kSelf); 1587 lua_getmetatable(L_, kSelf);
1589 lua_getfield(L, -1, "cached_error"); 1588 lua_getfield(L_, -1, "cached_error");
1590 lua_pushliteral(L, "Unknown key: "); 1589 lua_pushliteral(L_, "Unknown key: ");
1591 lua_pushvalue(L, kKey); 1590 lua_pushvalue(L_, kKey);
1592 lua_concat(L, 2); 1591 lua_concat(L_, 2);
1593 lua_call(L, 1, 0); // error( "Unknown key: " .. key) -> doesn't return 1592 lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return
1594 return 0; 1593 return 0;
1595} 1594}
1596 1595
@@ -1601,8 +1600,8 @@ LUAG_FUNC(thread_index)
1601// Return a list of all known lanes 1600// Return a list of all known lanes
1602LUAG_FUNC(threads) 1601LUAG_FUNC(threads)
1603{ 1602{
1604 int const top{ lua_gettop(L) }; 1603 int const top{ lua_gettop(L_) };
1605 Universe* const U{ universe_get(L) }; 1604 Universe* const U{ universe_get(L_) };
1606 1605
1607 // List _all_ still running threads 1606 // List _all_ still running threads
1608 // 1607 //
@@ -1611,20 +1610,20 @@ LUAG_FUNC(threads)
1611 { 1610 {
1612 Lane* lane{ U->tracking_first }; 1611 Lane* lane{ U->tracking_first };
1613 int index = 0; 1612 int index = 0;
1614 lua_newtable(L); // {} 1613 lua_newtable(L_); // {}
1615 while (lane != TRACKING_END) 1614 while (lane != TRACKING_END)
1616 { 1615 {
1617 // insert a { name, status } tuple, so that several lanes with the same name can't clobber each other 1616 // insert a { name, status } tuple, so that several lanes with the same name can't clobber each other
1618 lua_newtable(L); // {} {} 1617 lua_newtable(L_); // {} {}
1619 lua_pushstring(L, lane->debug_name); // {} {} "name" 1618 lua_pushstring(L_, lane->debug_name); // {} {} "name"
1620 lua_setfield(L, -2, "name"); // {} {} 1619 lua_setfield(L_, -2, "name"); // {} {}
1621 lane->pushThreadStatus(L); // {} {} "status" 1620 lane->pushThreadStatus(L_); // {} {} "status"
1622 lua_setfield(L, -2, "status"); // {} {} 1621 lua_setfield(L_, -2, "status"); // {} {}
1623 lua_rawseti(L, -2, ++index); // {} 1622 lua_rawseti(L_, -2, ++index); // {}
1624 lane = lane->tracking_next; 1623 lane = lane->tracking_next;
1625 } 1624 }
1626 } 1625 }
1627 return lua_gettop(L) - top; // 0 or 1 1626 return lua_gettop(L_) - top; // 0 or 1
1628} 1627}
1629#endif // HAVE_LANE_TRACKING() 1628#endif // HAVE_LANE_TRACKING()
1630 1629
@@ -1643,7 +1642,7 @@ LUAG_FUNC(now_secs)
1643 auto const now{ std::chrono::system_clock::now() }; 1642 auto const now{ std::chrono::system_clock::now() };
1644 lua_Duration duration { now.time_since_epoch() }; 1643 lua_Duration duration { now.time_since_epoch() };
1645 1644
1646 lua_pushnumber(L, duration.count()); 1645 lua_pushnumber(L_, duration.count());
1647 return 1; 1646 return 1;
1648} 1647}
1649 1648
@@ -1664,8 +1663,8 @@ LUAG_FUNC(wakeup_conv)
1664 // .yday (day of the year) 1663 // .yday (day of the year)
1665 // .isdst (daylight saving on/off) 1664 // .isdst (daylight saving on/off)
1666 1665
1667 STACK_CHECK_START_REL(L, 0); 1666 STACK_CHECK_START_REL(L_, 0);
1668 auto readInteger = [L](char const* name_) 1667 auto readInteger = [L = L_](char const* name_)
1669 { 1668 {
1670 lua_getfield(L, 1, name_); 1669 lua_getfield(L, 1, name_);
1671 lua_Integer const val{ lua_tointeger(L, -1) }; 1670 lua_Integer const val{ lua_tointeger(L, -1) };
@@ -1678,15 +1677,15 @@ LUAG_FUNC(wakeup_conv)
1678 int const hour{ readInteger("hour") }; 1677 int const hour{ readInteger("hour") };
1679 int const min{ readInteger("min") }; 1678 int const min{ readInteger("min") };
1680 int const sec{ readInteger("sec") }; 1679 int const sec{ readInteger("sec") };
1681 STACK_CHECK(L, 0); 1680 STACK_CHECK(L_, 0);
1682 1681
1683 // If Lua table has '.isdst' we trust that. If it does not, we'll let 1682 // If Lua table has '.isdst' we trust that. If it does not, we'll let
1684 // 'mktime' decide on whether the time is within DST or not (value -1). 1683 // 'mktime' decide on whether the time is within DST or not (value -1).
1685 // 1684 //
1686 lua_getfield(L, 1, "isdst" ); 1685 lua_getfield(L_, 1, "isdst" );
1687 int const isdst{ lua_isboolean(L, -1) ? lua_toboolean(L, -1) : -1 }; 1686 int const isdst{ lua_isboolean(L_, -1) ? lua_toboolean(L_, -1) : -1 };
1688 lua_pop(L,1); 1687 lua_pop(L_,1);
1689 STACK_CHECK(L, 0); 1688 STACK_CHECK(L_, 0);
1690 1689
1691 std::tm t{}; 1690 std::tm t{};
1692 t.tm_year = year - 1900; 1691 t.tm_year = year - 1900;
@@ -1697,7 +1696,7 @@ LUAG_FUNC(wakeup_conv)
1697 t.tm_sec= sec; // 0..60 1696 t.tm_sec= sec; // 0..60
1698 t.tm_isdst= isdst; // 0/1/negative 1697 t.tm_isdst= isdst; // 0/1/negative
1699 1698
1700 lua_pushnumber(L, static_cast<lua_Number>(std::mktime(&t))); // resolution: 1 second 1699 lua_pushnumber(L_, static_cast<lua_Number>(std::mktime(&t))); // resolution: 1 second
1701 return 1; 1700 return 1;
1702} 1701}
1703 1702
@@ -1705,7 +1704,7 @@ LUAG_FUNC(wakeup_conv)
1705// ######################################## Module linkage ######################################### 1704// ######################################## Module linkage #########################################
1706// ################################################################################################# 1705// #################################################################################################
1707 1706
1708extern int LG_linda(lua_State* L); 1707extern int LG_linda(lua_State* L_);
1709static struct luaL_Reg const lanes_functions[] = 1708static struct luaL_Reg const lanes_functions[] =
1710{ 1709{
1711 { "linda", LG_linda }, 1710 { "linda", LG_linda },
@@ -1740,148 +1739,148 @@ LUAG_FUNC(configure)
1740 ); 1739 );
1741 } 1740 }
1742 1741
1743 Universe* U = universe_get(L); 1742 Universe* U = universe_get(L_);
1744 bool const from_master_state{ U == nullptr }; 1743 bool const from_master_state{ U == nullptr };
1745 char const* name = luaL_checkstring(L, lua_upvalueindex(1)); 1744 char const* name = luaL_checkstring(L_, lua_upvalueindex(1));
1746 LUA_ASSERT(L, lua_type(L, 1) == LUA_TTABLE); 1745 LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE);
1747 1746
1748 STACK_GROW(L, 4); 1747 STACK_GROW(L_, 4);
1749 STACK_CHECK_START_ABS(L, 1); // settings 1748 STACK_CHECK_START_ABS(L_, 1); // settings
1750 1749
1751 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); 1750 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L));
1752 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 1751 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U });
1753 1752
1754 if (U == nullptr) 1753 if (U == nullptr)
1755 { 1754 {
1756 U = universe_create(L); // settings universe 1755 U = universe_create(L_); // settings universe
1757 DEBUGSPEW_CODE(DebugSpewIndentScope scope2{ U }); 1756 DEBUGSPEW_CODE(DebugSpewIndentScope scope2{ U });
1758 lua_newtable( L); // settings universe mt 1757 lua_newtable(L_); // settings universe mt
1759 lua_getfield(L, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout 1758 lua_getfield(L_, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout
1760 lua_getfield(L, 1, "shutdown_mode"); // settings universe mt shutdown_timeout shutdown_mode 1759 lua_getfield(L_, 1, "shutdown_mode"); // settings universe mt shutdown_timeout shutdown_mode
1761 lua_pushcclosure(L, universe_gc, 2); // settings universe mt universe_gc 1760 lua_pushcclosure(L_, universe_gc, 2); // settings universe mt universe_gc
1762 lua_setfield(L, -2, "__gc"); // settings universe mt 1761 lua_setfield(L_, -2, "__gc"); // settings universe mt
1763 lua_setmetatable(L, -2); // settings universe 1762 lua_setmetatable(L_, -2); // settings universe
1764 lua_pop(L, 1); // settings 1763 lua_pop(L_, 1); // settings
1765 lua_getfield(L, 1, "verbose_errors"); // settings verbose_errors 1764 lua_getfield(L_, 1, "verbose_errors"); // settings verbose_errors
1766 U->verboseErrors = lua_toboolean(L, -1) ? true : false; 1765 U->verboseErrors = lua_toboolean(L_, -1) ? true : false;
1767 lua_pop(L, 1); // settings 1766 lua_pop(L_, 1); // settings
1768 lua_getfield(L, 1, "demote_full_userdata"); // settings demote_full_userdata 1767 lua_getfield(L_, 1, "demote_full_userdata"); // settings demote_full_userdata
1769 U->demoteFullUserdata = lua_toboolean(L, -1) ? true : false; 1768 U->demoteFullUserdata = lua_toboolean(L_, -1) ? true : false;
1770 lua_pop(L, 1); // settings 1769 lua_pop(L_, 1); // settings
1771#if HAVE_LANE_TRACKING() 1770#if HAVE_LANE_TRACKING()
1772 lua_getfield(L, 1, "track_lanes"); // settings track_lanes 1771 lua_getfield(L_, 1, "track_lanes"); // settings track_lanes
1773 U->tracking_first = lua_toboolean(L, -1) ? TRACKING_END : nullptr; 1772 U->tracking_first = lua_toboolean(L_, -1) ? TRACKING_END : nullptr;
1774 lua_pop(L, 1); // settings 1773 lua_pop(L_, 1); // settings
1775#endif // HAVE_LANE_TRACKING() 1774#endif // HAVE_LANE_TRACKING()
1776 // Linked chains handling 1775 // Linked chains handling
1777 U->selfdestruct_first = SELFDESTRUCT_END; 1776 U->selfdestruct_first = SELFDESTRUCT_END;
1778 initialize_allocator_function( U, L); 1777 initialize_allocator_function( U, L_);
1779 initialize_on_state_create( U, L); 1778 initialize_on_state_create( U, L_);
1780 init_keepers( U, L); 1779 init_keepers( U, L_);
1781 STACK_CHECK(L, 1); 1780 STACK_CHECK(L_, 1);
1782 1781
1783 // Initialize 'timer_deep'; a common Linda object shared by all states 1782 // Initialize 'timer_deep'; a common Linda object shared by all states
1784 lua_pushcfunction(L, LG_linda); // settings lanes.linda 1783 lua_pushcfunction(L_, LG_linda); // settings lanes.linda
1785 lua_pushliteral(L, "lanes-timer"); // settings lanes.linda "lanes-timer" 1784 lua_pushliteral(L_, "lanes-timer"); // settings lanes.linda "lanes-timer"
1786 lua_call(L, 1, 1); // settings linda 1785 lua_call(L_, 1, 1); // settings linda
1787 STACK_CHECK(L, 2); 1786 STACK_CHECK(L_, 2);
1788 1787
1789 // Proxy userdata contents is only a 'DeepPrelude*' pointer 1788 // Proxy userdata contents is only a 'DeepPrelude*' pointer
1790 U->timer_deep = *lua_tofulluserdata<DeepPrelude*>(L, -1); 1789 U->timer_deep = *lua_tofulluserdata<DeepPrelude*>(L_, -1);
1791 // increment refcount so that this linda remains alive as long as the universe exists. 1790 // increment refcount so that this linda remains alive as long as the universe exists.
1792 U->timer_deep->m_refcount.fetch_add(1, std::memory_order_relaxed); 1791 U->timer_deep->m_refcount.fetch_add(1, std::memory_order_relaxed);
1793 lua_pop(L, 1); // settings 1792 lua_pop(L_, 1); // settings
1794 } 1793 }
1795 STACK_CHECK(L, 1); 1794 STACK_CHECK(L_, 1);
1796 1795
1797 // Serialize calls to 'require' from now on, also in the primary state 1796 // Serialize calls to 'require' from now on, also in the primary state
1798 serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); 1797 serialize_require( DEBUGSPEW_PARAM_COMMA( U) L_);
1799 1798
1800 // Retrieve main module interface table 1799 // Retrieve main module interface table
1801 lua_pushvalue(L, lua_upvalueindex( 2)); // settings M 1800 lua_pushvalue(L_, lua_upvalueindex( 2)); // settings M
1802 // remove configure() (this function) from the module interface 1801 // remove configure() (this function) from the module interface
1803 lua_pushnil( L); // settings M nil 1802 lua_pushnil( L_); // settings M nil
1804 lua_setfield(L, -2, "configure"); // settings M 1803 lua_setfield(L_, -2, "configure"); // settings M
1805 // add functions to the module's table 1804 // add functions to the module's table
1806 luaG_registerlibfuncs(L, lanes_functions); 1805 luaG_registerlibfuncs(L_, lanes_functions);
1807#if HAVE_LANE_TRACKING() 1806#if HAVE_LANE_TRACKING()
1808 // register core.threads() only if settings say it should be available 1807 // register core.threads() only if settings say it should be available
1809 if (U->tracking_first != nullptr) 1808 if (U->tracking_first != nullptr)
1810 { 1809 {
1811 lua_pushcfunction(L, LG_threads); // settings M LG_threads() 1810 lua_pushcfunction(L_, LG_threads); // settings M LG_threads()
1812 lua_setfield(L, -2, "threads"); // settings M 1811 lua_setfield(L_, -2, "threads"); // settings M
1813 } 1812 }
1814#endif // HAVE_LANE_TRACKING() 1813#endif // HAVE_LANE_TRACKING()
1815 STACK_CHECK(L, 2); 1814 STACK_CHECK(L_, 2);
1816 1815
1817 { 1816 {
1818 char const* errmsg{ DeepFactory::PushDeepProxy(DestState{ L }, U->timer_deep, 0, LookupMode::LaneBody) }; // settings M timer_deep 1817 char const* errmsg{ DeepFactory::PushDeepProxy(DestState{ L_ }, U->timer_deep, 0, LookupMode::LaneBody) }; // settings M timer_deep
1819 if (errmsg != nullptr) 1818 if (errmsg != nullptr)
1820 { 1819 {
1821 raise_luaL_error(L, errmsg); 1820 raise_luaL_error(L_, errmsg);
1822 } 1821 }
1823 lua_setfield(L, -2, "timer_gateway"); // settings M 1822 lua_setfield(L_, -2, "timer_gateway"); // settings M
1824 } 1823 }
1825 STACK_CHECK(L, 2); 1824 STACK_CHECK(L_, 2);
1826 1825
1827 // prepare the metatable for threads 1826 // prepare the metatable for threads
1828 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } 1827 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname }
1829 // 1828 //
1830 if (luaL_newmetatable(L, "Lane")) // settings M mt 1829 if (luaL_newmetatable(L_, "Lane")) // settings M mt
1831 { 1830 {
1832 lua_pushcfunction(L, lane_gc); // settings M mt lane_gc 1831 lua_pushcfunction(L_, lane_gc); // settings M mt lane_gc
1833 lua_setfield(L, -2, "__gc"); // settings M mt 1832 lua_setfield(L_, -2, "__gc"); // settings M mt
1834 lua_pushcfunction(L, LG_thread_index); // settings M mt LG_thread_index 1833 lua_pushcfunction(L_, LG_thread_index); // settings M mt LG_thread_index
1835 lua_setfield(L, -2, "__index"); // settings M mt 1834 lua_setfield(L_, -2, "__index"); // settings M mt
1836 lua_getglobal(L, "error"); // settings M mt error 1835 lua_getglobal(L_, "error"); // settings M mt error
1837 LUA_ASSERT(L, lua_isfunction(L, -1)); 1836 LUA_ASSERT(L_, lua_isfunction(L_, -1));
1838 lua_setfield(L, -2, "cached_error"); // settings M mt 1837 lua_setfield(L_, -2, "cached_error"); // settings M mt
1839 lua_getglobal(L, "tostring"); // settings M mt tostring 1838 lua_getglobal(L_, "tostring"); // settings M mt tostring
1840 LUA_ASSERT(L, lua_isfunction(L, -1)); 1839 LUA_ASSERT(L_, lua_isfunction(L_, -1));
1841 lua_setfield(L, -2, "cached_tostring"); // settings M mt 1840 lua_setfield(L_, -2, "cached_tostring"); // settings M mt
1842 lua_pushcfunction(L, LG_thread_join); // settings M mt LG_thread_join 1841 lua_pushcfunction(L_, LG_thread_join); // settings M mt LG_thread_join
1843 lua_setfield(L, -2, "join"); // settings M mt 1842 lua_setfield(L_, -2, "join"); // settings M mt
1844 lua_pushcfunction(L, LG_get_debug_threadname); // settings M mt LG_get_debug_threadname 1843 lua_pushcfunction(L_, LG_get_debug_threadname); // settings M mt LG_get_debug_threadname
1845 lua_setfield(L, -2, "get_debug_threadname"); // settings M mt 1844 lua_setfield(L_, -2, "get_debug_threadname"); // settings M mt
1846 lua_pushcfunction(L, LG_thread_cancel); // settings M mt LG_thread_cancel 1845 lua_pushcfunction(L_, LG_thread_cancel); // settings M mt LG_thread_cancel
1847 lua_setfield(L, -2, "cancel"); // settings M mt 1846 lua_setfield(L_, -2, "cancel"); // settings M mt
1848 lua_pushliteral(L, "Lane"); // settings M mt "Lane" 1847 lua_pushliteral(L_, "Lane"); // settings M mt "Lane"
1849 lua_setfield(L, -2, "__metatable"); // settings M mt 1848 lua_setfield(L_, -2, "__metatable"); // settings M mt
1850 } 1849 }
1851 1850
1852 lua_pushcclosure(L, LG_lane_new, 1); // settings M lane_new 1851 lua_pushcclosure(L_, LG_lane_new, 1); // settings M lane_new
1853 lua_setfield(L, -2, "lane_new"); // settings M 1852 lua_setfield(L_, -2, "lane_new"); // settings M
1854 1853
1855 // we can't register 'lanes.require' normally because we want to create an upvalued closure 1854 // we can't register 'lanes.require' normally because we want to create an upvalued closure
1856 lua_getglobal(L, "require"); // settings M require 1855 lua_getglobal(L_, "require"); // settings M require
1857 lua_pushcclosure(L, LG_require, 1); // settings M lanes.require 1856 lua_pushcclosure(L_, LG_require, 1); // settings M lanes.require
1858 lua_setfield(L, -2, "require"); // settings M 1857 lua_setfield(L_, -2, "require"); // settings M
1859 1858
1860 lua_pushfstring( 1859 lua_pushfstring(
1861 L, "%d.%d.%d" 1860 L_, "%d.%d.%d"
1862 , LANES_VERSION_MAJOR, LANES_VERSION_MINOR, LANES_VERSION_PATCH 1861 , LANES_VERSION_MAJOR, LANES_VERSION_MINOR, LANES_VERSION_PATCH
1863 ); // settings M VERSION 1862 ); // settings M VERSION
1864 lua_setfield(L, -2, "version"); // settings M 1863 lua_setfield(L_, -2, "version"); // settings M
1865 1864
1866 lua_pushinteger(L, kThreadPrioMax); // settings M kThreadPrioMax 1865 lua_pushinteger(L_, kThreadPrioMax); // settings M kThreadPrioMax
1867 lua_setfield(L, -2, "max_prio"); // settings M 1866 lua_setfield(L_, -2, "max_prio"); // settings M
1868 1867
1869 kCancelError.pushKey(L); // settings M kCancelError 1868 kCancelError.pushKey(L_); // settings M kCancelError
1870 lua_setfield(L, -2, "cancel_error"); // settings M 1869 lua_setfield(L_, -2, "cancel_error"); // settings M
1871 1870
1872 kNilSentinel.pushKey(L); // settings M kNilSentinel 1871 kNilSentinel.pushKey(L_); // settings M kNilSentinel
1873 lua_setfield(L, -2, "null"); // settings M 1872 lua_setfield(L_, -2, "null"); // settings M
1874 1873
1875 STACK_CHECK(L, 2); // reference stack contains only the function argument 'settings' 1874 STACK_CHECK(L_, 2); // reference stack contains only the function argument 'settings'
1876 // we'll need this every time we transfer some C function from/to this state 1875 // we'll need this every time we transfer some C function from/to this state
1877 kLookupRegKey.setValue(L, [](lua_State* L) { lua_newtable(L); }); // settings M 1876 kLookupRegKey.setValue(L_, [](lua_State* L_) { lua_newtable(L_); }); // settings M
1878 STACK_CHECK(L, 2); 1877 STACK_CHECK(L_, 2);
1879 1878
1880 // register all native functions found in that module in the transferable functions database 1879 // register all native functions found in that module in the transferable functions database
1881 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) 1880 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
1882 // for example in package.loaded["lanes.core"].* 1881 // for example in package.loaded["lanes.core"].*
1883 populate_func_lookup_table(L, -1, name); 1882 populate_func_lookup_table(L_, -1, name);
1884 STACK_CHECK(L, 2); 1883 STACK_CHECK(L_, 2);
1885 1884
1886 // record all existing C/JIT-fast functions 1885 // record all existing C/JIT-fast functions
1887 // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack 1886 // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
@@ -1890,15 +1889,15 @@ LUAG_FUNC(configure)
1890 // don't do this when called during the initialization of a new lane, 1889 // don't do this when called during the initialization of a new lane,
1891 // because we will do it after on_state_create() is called, 1890 // because we will do it after on_state_create() is called,
1892 // and we don't want to skip _G because of caching in case globals are created then 1891 // and we don't want to skip _G because of caching in case globals are created then
1893 lua_pushglobaltable( L); // settings M _G 1892 lua_pushglobaltable(L_); // settings M _G
1894 populate_func_lookup_table(L, -1, nullptr); 1893 populate_func_lookup_table(L_, -1, nullptr);
1895 lua_pop(L, 1); // settings M 1894 lua_pop(L_, 1); // settings M
1896 } 1895 }
1897 lua_pop(L, 1); // settings 1896 lua_pop(L_, 1); // settings
1898 1897
1899 // set _R[kConfigRegKey] = settings 1898 // set _R[kConfigRegKey] = settings
1900 kConfigRegKey.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); 1899 kConfigRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); });
1901 STACK_CHECK(L, 1); 1900 STACK_CHECK(L_, 1);
1902 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); 1901 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L));
1903 // Return the settings table 1902 // Return the settings table
1904 return 1; 1903 return 1;
@@ -1962,70 +1961,70 @@ static void EnableCrashingOnCrashes(void)
1962} 1961}
1963#endif // PLATFORM_WIN32 && !defined NDEBUG 1962#endif // PLATFORM_WIN32 && !defined NDEBUG
1964 1963
1965LANES_API int luaopen_lanes_core( lua_State* L) 1964LANES_API int luaopen_lanes_core( lua_State* L_)
1966{ 1965{
1967#if defined PLATFORM_WIN32 && !defined NDEBUG 1966#if defined PLATFORM_WIN32 && !defined NDEBUG
1968 EnableCrashingOnCrashes(); 1967 EnableCrashingOnCrashes();
1969#endif // defined PLATFORM_WIN32 && !defined NDEBUG 1968#endif // defined PLATFORM_WIN32 && !defined NDEBUG
1970 1969
1971 STACK_GROW(L, 4); 1970 STACK_GROW(L_, 4);
1972 STACK_CHECK_START_REL(L, 0); 1971 STACK_CHECK_START_REL(L_, 0);
1973 1972
1974 // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too 1973 // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too
1975 lua_getglobal(L, "jit"); // {jit?} 1974 lua_getglobal(L_, "jit"); // {jit?}
1976#if LUAJIT_FLAVOR() == 0 1975#if LUAJIT_FLAVOR() == 0
1977 if (!lua_isnil(L, -1)) 1976 if (!lua_isnil(L_, -1))
1978 raise_luaL_error(L, "Lanes is built for PUC-Lua, don't run from LuaJIT"); 1977 raise_luaL_error(L_, "Lanes is built for PUC-Lua, don't run from LuaJIT");
1979#else 1978#else
1980 if (lua_isnil(L, -1)) 1979 if (lua_isnil(L_, -1))
1981 raise_luaL_error(L, "Lanes is built for LuaJIT, don't run from PUC-Lua"); 1980 raise_luaL_error(L_, "Lanes is built for LuaJIT, don't run from PUC-Lua");
1982#endif 1981#endif
1983 lua_pop(L, 1); // 1982 lua_pop(L_, 1); //
1984 STACK_CHECK(L, 0); 1983 STACK_CHECK(L_, 0);
1985 1984
1986 // Create main module interface table 1985 // Create main module interface table
1987 // we only have 1 closure, which must be called to configure Lanes 1986 // we only have 1 closure, which must be called to configure Lanes
1988 lua_newtable(L); // M 1987 lua_newtable(L_); // M
1989 lua_pushvalue(L, 1); // M "lanes.core" 1988 lua_pushvalue(L_, 1); // M "lanes.core"
1990 lua_pushvalue(L, -2); // M "lanes.core" M 1989 lua_pushvalue(L_, -2); // M "lanes.core" M
1991 lua_pushcclosure(L, LG_configure, 2); // M LG_configure() 1990 lua_pushcclosure(L_, LG_configure, 2); // M LG_configure()
1992 kConfigRegKey.pushValue(L); // M LG_configure() settings 1991 kConfigRegKey.pushValue(L_); // M LG_configure() settings
1993 if (!lua_isnil(L, -1)) // this is not the first require "lanes.core": call configure() immediately 1992 if (!lua_isnil(L_, -1)) // this is not the first require "lanes.core": call configure() immediately
1994 { 1993 {
1995 lua_pushvalue(L, -1); // M LG_configure() settings settings 1994 lua_pushvalue(L_, -1); // M LG_configure() settings settings
1996 lua_setfield(L, -4, "settings"); // M LG_configure() settings 1995 lua_setfield(L_, -4, "settings"); // M LG_configure() settings
1997 lua_call(L, 1, 0); // M 1996 lua_call(L_, 1, 0); // M
1998 } 1997 }
1999 else 1998 else
2000 { 1999 {
2001 // will do nothing on first invocation, as we haven't stored settings in the registry yet 2000 // will do nothing on first invocation, as we haven't stored settings in the registry yet
2002 lua_setfield(L, -3, "settings"); // M LG_configure() 2001 lua_setfield(L_, -3, "settings"); // M LG_configure()
2003 lua_setfield(L, -2, "configure"); // M 2002 lua_setfield(L_, -2, "configure"); // M
2004 } 2003 }
2005 2004
2006 STACK_CHECK(L, 1); 2005 STACK_CHECK(L_, 1);
2007 return 1; 2006 return 1;
2008} 2007}
2009 2008
2010[[nodiscard]] static int default_luaopen_lanes(lua_State* L) 2009[[nodiscard]] static int default_luaopen_lanes(lua_State* L_)
2011{ 2010{
2012 int const rc{ luaL_loadfile(L, "lanes.lua") || lua_pcall(L, 0, 1, 0) }; 2011 int const rc{ luaL_loadfile(L_, "lanes.lua") || lua_pcall(L_, 0, 1, 0) };
2013 if (rc != LUA_OK) 2012 if (rc != LUA_OK)
2014 { 2013 {
2015 raise_luaL_error(L, "failed to initialize embedded Lanes"); 2014 raise_luaL_error(L_, "failed to initialize embedded Lanes");
2016 } 2015 }
2017 return 1; 2016 return 1;
2018} 2017}
2019 2018
2020// call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application 2019// call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application
2021LANES_API void luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) 2020LANES_API void luaopen_lanes_embedded( lua_State* L_, lua_CFunction _luaopen_lanes)
2022{ 2021{
2023 STACK_CHECK_START_REL(L, 0); 2022 STACK_CHECK_START_REL(L_, 0);
2024 // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded 2023 // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded
2025 luaL_requiref(L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core 2024 luaL_requiref(L_, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core
2026 lua_pop(L, 1); // ... 2025 lua_pop(L_, 1); // ...
2027 STACK_CHECK(L, 0); 2026 STACK_CHECK(L_, 0);
2028 // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it 2027 // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it
2029 luaL_requiref(L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes 2028 luaL_requiref(L_, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes
2030 STACK_CHECK(L, 1); 2029 STACK_CHECK(L_, 1);
2031} 2030}