diff options
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r-- | src/lanes.cpp | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index b3f7be7..7b730cd 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -205,32 +205,33 @@ LUAG_FUNC(register) | |||
205 | 205 | ||
206 | // ################################################################################################# | 206 | // ################################################################################################# |
207 | 207 | ||
208 | //--- | 208 | //--- [] means can be nil |
209 | // lane_ud = lane_new( function | 209 | // lane_ud = lane_new( function |
210 | // , [libs_str] | 210 | // , [libs_str] |
211 | // , [priority_int=0] | 211 | // , [priority_int] |
212 | // , [globals_tbl] | 212 | // , [globals_tbl] |
213 | // , [package_tbl] | 213 | // , [package_tbl] |
214 | // , [required_tbl] | 214 | // , [required_tbl] |
215 | // , [gc_cb_func] | 215 | // , [gc_cb_func] |
216 | // , [name] | 216 | // , [name] |
217 | // , error_trace_level | ||
217 | // [, ... args ...]) | 218 | // [, ... args ...]) |
218 | // | 219 | // |
219 | // Upvalues: metatable to use for 'lane_ud' | 220 | // Upvalues: metatable to use for 'lane_ud' |
220 | // | 221 | // |
221 | LUAG_FUNC(lane_new) | 222 | LUAG_FUNC(lane_new) |
222 | { | 223 | { |
223 | // first 8 args: func libs priority globals package required gc_cb name | 224 | // first 9 args: func libs priority globals package required gc_cb name error_trace_level |
224 | char const* const _libs_str{ lua_tostring(L_, 2) }; | 225 | char const* const _libs_str{ lua_tostring(L_, 2) }; |
225 | bool const _have_priority{ !lua_isnoneornil(L_, 3) }; | 226 | bool const _have_priority{ !lua_isnoneornil(L_, 3) }; |
226 | int const _priority{ _have_priority ? static_cast<int>(lua_tointeger(L_, 3)) : kThreadPrioDefault }; | ||
227 | int const _globals_idx{ lua_isnoneornil(L_, 4) ? 0 : 4 }; | 227 | int const _globals_idx{ lua_isnoneornil(L_, 4) ? 0 : 4 }; |
228 | int const _package_idx{ lua_isnoneornil(L_, 5) ? 0 : 5 }; | 228 | int const _package_idx{ lua_isnoneornil(L_, 5) ? 0 : 5 }; |
229 | int const _required_idx{ lua_isnoneornil(L_, 6) ? 0 : 6 }; | 229 | int const _required_idx{ lua_isnoneornil(L_, 6) ? 0 : 6 }; |
230 | int const _gc_cb_idx{ lua_isnoneornil(L_, 7) ? 0 : 7 }; | 230 | int const _gc_cb_idx{ lua_isnoneornil(L_, 7) ? 0 : 7 }; |
231 | int const _name_idx{ lua_isnoneornil(L_, 8) ? 0 : 8 }; | 231 | int const _name_idx{ lua_isnoneornil(L_, 8) ? 0 : 8 }; |
232 | int const _error_trace_level_idx{ 9 }; | ||
232 | 233 | ||
233 | static constexpr int kFixedArgsIdx{ 8 }; | 234 | static constexpr int kFixedArgsIdx{ 9 }; |
234 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; | 235 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; |
235 | Universe* const _U{ universe_get(L_) }; | 236 | Universe* const _U{ universe_get(L_) }; |
236 | LUA_ASSERT(L_, _nargs >= 0); | 237 | LUA_ASSERT(L_, _nargs >= 0); |
@@ -238,6 +239,7 @@ LUAG_FUNC(lane_new) | |||
238 | // public Lanes API accepts a generic range -3/+3 | 239 | // public Lanes API accepts a generic range -3/+3 |
239 | // that will be remapped into the platform-specific scheduler priority scheme | 240 | // that will be remapped into the platform-specific scheduler priority scheme |
240 | // On some platforms, -3 is equivalent to -2 and +3 to +2 | 241 | // On some platforms, -3 is equivalent to -2 and +3 to +2 |
242 | int const _priority{ _have_priority ? static_cast<int>(lua_tointeger(L_, 3)) : kThreadPrioDefault }; | ||
241 | if (_have_priority && (_priority < kThreadPrioMin || _priority > kThreadPrioMax)) { | 243 | if (_have_priority && (_priority < kThreadPrioMin || _priority > kThreadPrioMax)) { |
242 | raise_luaL_error(L_, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority); | 244 | raise_luaL_error(L_, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority); |
243 | } | 245 | } |
@@ -246,11 +248,11 @@ LUAG_FUNC(lane_new) | |||
246 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U))); | 248 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U))); |
247 | 249 | ||
248 | // populate with selected libraries at the same time. | 250 | // populate with selected libraries at the same time. |
249 | lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [8 args] ... L2: | 251 | lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [9 args] ... L2: |
250 | STACK_CHECK_START_REL(_L2, 0); | 252 | STACK_CHECK_START_REL(_L2, 0); |
251 | 253 | ||
252 | // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 254 | // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
253 | Lane* const _lane{ new (_U) Lane{ _U, _L2 } }; | 255 | Lane* const _lane{ new (_U) Lane{ _U, _L2, static_cast<Lane::ErrorTraceLevel>(lua_tointeger(L_, _error_trace_level_idx)) } }; |
254 | if (_lane == nullptr) { | 256 | if (_lane == nullptr) { |
255 | raise_luaL_error(L_, "could not create lane: out of memory"); | 257 | raise_luaL_error(L_, "could not create lane: out of memory"); |
256 | } | 258 | } |
@@ -410,7 +412,7 @@ LUAG_FUNC(lane_new) | |||
410 | lua_pop(_L2, 1); // L_: [8 args] args... n "modname" L2: | 412 | lua_pop(_L2, 1); // L_: [8 args] args... n "modname" L2: |
411 | } | 413 | } |
412 | } | 414 | } |
413 | lua_pop(L_, 1); // L_: func libs priority globals package required gc_cb [... args ...] n | 415 | lua_pop(L_, 1); // L_: func libs priority globals package required gc_cb [... args ...] n |
414 | ++_nbRequired; | 416 | ++_nbRequired; |
415 | } // L_: [8 args] args... | 417 | } // L_: [8 args] args... |
416 | } | 418 | } |
@@ -443,35 +445,36 @@ LUAG_FUNC(lane_new) | |||
443 | STACK_CHECK(_L2, 0); | 445 | STACK_CHECK(_L2, 0); |
444 | 446 | ||
445 | // Lane main function | 447 | // Lane main function |
448 | int const errorHandlerCount{ _lane->pushErrorHandler() }; // L2: eh? | ||
446 | LuaType const _func_type{ lua_type_as_enum(L_, 1) }; | 449 | LuaType const _func_type{ lua_type_as_enum(L_, 1) }; |
447 | if (_func_type == LuaType::FUNCTION) { | 450 | if (_func_type == LuaType::FUNCTION) { |
448 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U))); | 451 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U))); |
449 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 452 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
450 | lua_pushvalue(L_, 1); // L_: [8 args] args... func L2: | 453 | lua_pushvalue(L_, 1); // L_: [8 args] args... func L2: eh? |
451 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; | 454 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; |
452 | InterCopyResult const _res{ _c.inter_move(1) }; // L_: [8 args] args... L2: func | 455 | InterCopyResult const _res{ _c.inter_move(1) }; // L_: [8 args] args... L2: eh? func |
453 | if (_res != InterCopyResult::Success) { | 456 | if (_res != InterCopyResult::Success) { |
454 | raise_luaL_error(L_, "tried to copy unsupported types"); | 457 | raise_luaL_error(L_, "tried to copy unsupported types"); |
455 | } | 458 | } |
456 | } else if (_func_type == LuaType::STRING) { | 459 | } else if (_func_type == LuaType::STRING) { |
457 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U))); | 460 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U))); |
458 | // compile the string | 461 | // compile the string |
459 | if (luaL_loadstring(_L2, lua_tostring(L_, 1)) != 0) { // L_: [8 args] args... L2: func | 462 | if (luaL_loadstring(_L2, lua_tostring(L_, 1)) != 0) { // L_: [8 args] args... L2: eh? func |
460 | raise_luaL_error(L_, "error when parsing lane function code"); | 463 | raise_luaL_error(L_, "error when parsing lane function code"); |
461 | } | 464 | } |
462 | } else { | 465 | } else { |
463 | raise_luaL_error(L_, "Expected function, got %s", lua_typename(L_, _func_type)); | 466 | raise_luaL_error(L_, "Expected function, got %s", lua_typename(L_, _func_type)); |
464 | } | 467 | } |
465 | STACK_CHECK(L_, 0); | 468 | STACK_CHECK(L_, 0); |
466 | STACK_CHECK(_L2, 1); | 469 | STACK_CHECK(_L2, errorHandlerCount + 1); |
467 | LUA_ASSERT(L_, lua_isfunction(_L2, 1)); | 470 | LUA_ASSERT(L_, lua_isfunction(_L2, errorHandlerCount + 1)); |
468 | 471 | ||
469 | // revive arguments | 472 | // revive arguments |
470 | if (_nargs > 0) { | 473 | if (_nargs > 0) { |
471 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U))); | 474 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U))); |
472 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 475 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
473 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; | 476 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; |
474 | InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [8 args] L2: func args... | 477 | InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [8 args] L2: eh? func args... |
475 | if (res != InterCopyResult::Success) { | 478 | if (res != InterCopyResult::Success) { |
476 | raise_luaL_error(L_, "tried to copy unsupported types"); | 479 | raise_luaL_error(L_, "tried to copy unsupported types"); |
477 | } | 480 | } |
@@ -480,8 +483,8 @@ LUAG_FUNC(lane_new) | |||
480 | LUA_ASSERT(L_, lua_gettop(L_) == kFixedArgsIdx); | 483 | LUA_ASSERT(L_, lua_gettop(L_) == kFixedArgsIdx); |
481 | 484 | ||
482 | // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). | 485 | // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). |
483 | kLanePointerRegKey.setValue(_L2, [lane = _lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); });// L_: [8 args] L2: func args... | 486 | kLanePointerRegKey.setValue(_L2, [lane = _lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); });// L_: [8 args] L2: eh? func args... |
484 | STACK_CHECK(_L2, 1 + _nargs); | 487 | STACK_CHECK(_L2, errorHandlerCount + 1 + _nargs); |
485 | 488 | ||
486 | STACK_CHECK_RESET_REL(L_, 0); | 489 | STACK_CHECK_RESET_REL(L_, 0); |
487 | // all went well, the lane's thread can start working | 490 | // all went well, the lane's thread can start working |
@@ -579,7 +582,7 @@ LUAG_FUNC(wakeup_conv) | |||
579 | // ######################################## Module linkage ######################################### | 582 | // ######################################## Module linkage ######################################### |
580 | // ################################################################################################# | 583 | // ################################################################################################# |
581 | 584 | ||
582 | extern int LG_linda(lua_State* L_); | 585 | extern LUAG_FUNC(linda); |
583 | 586 | ||
584 | namespace global { | 587 | namespace global { |
585 | static struct luaL_Reg const sLanesFunctions[] = { | 588 | static struct luaL_Reg const sLanesFunctions[] = { |
@@ -700,9 +703,8 @@ LUAG_FUNC(configure) | |||
700 | STACK_CHECK(L_, 2); | 703 | STACK_CHECK(L_, 2); |
701 | 704 | ||
702 | // prepare the metatable for threads | 705 | // prepare the metatable for threads |
703 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } | 706 | // contains keys: { __gc, __index, cancel, join, get_debug_threadname } |
704 | Lane::PushMetatable(L_); | 707 | Lane::PushMetatable(L_); // L_: settings M {lane_mt} |
705 | |||
706 | lua_pushcclosure(L_, LG_lane_new, 1); // L_: settings M lane_new | 708 | lua_pushcclosure(L_, LG_lane_new, 1); // L_: settings M lane_new |
707 | lua_setfield(L_, -2, "lane_new"); // L_: settings M | 709 | lua_setfield(L_, -2, "lane_new"); // L_: settings M |
708 | 710 | ||