diff options
-rw-r--r-- | src/lane.cpp | 44 | ||||
-rw-r--r-- | src/lane.h | 2 | ||||
-rw-r--r-- | src/lanes.cpp | 8 | ||||
-rw-r--r-- | src/lanes.h | 4 |
4 files changed, 30 insertions, 28 deletions
diff --git a/src/lane.cpp b/src/lane.cpp index e38c4bb..baba0fa 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -480,7 +480,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
480 | // ########################################## Finalizer ############################################ | 480 | // ########################################## Finalizer ############################################ |
481 | // ################################################################################################# | 481 | // ################################################################################################# |
482 | 482 | ||
483 | static [[nodiscard]] int push_stack_trace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] int const stk_base_) | 483 | [[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] int const stk_base_) |
484 | { | 484 | { |
485 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry | 485 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry |
486 | int const _top{ lua_gettop(L_) }; | 486 | int const _top{ lua_gettop(L_) }; |
@@ -532,7 +532,7 @@ static [[nodiscard]] int push_stack_trace(lua_State* const L_, Lane::ErrorTraceL | |||
532 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. | 532 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. |
533 | // | 533 | // |
534 | 534 | ||
535 | [[nodiscard]] static LuaError run_finalizers(Lane* const lane_, Lane::ErrorTraceLevel errorTraceLevel_, LuaError lua_rc_) | 535 | [[nodiscard]] static LuaError run_finalizers(Lane* const lane_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const lua_rc_) |
536 | { | 536 | { |
537 | // if we are a coroutine, we can't run the finalizers in the coroutine state! | 537 | // if we are a coroutine, we can't run the finalizers in the coroutine state! |
538 | lua_State* const _L{ lane_->S }; | 538 | lua_State* const _L{ lane_->S }; |
@@ -581,7 +581,7 @@ static [[nodiscard]] int push_stack_trace(lua_State* const L_, Lane::ErrorTraceL | |||
581 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace | 581 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace |
582 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? | 582 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? |
583 | if (_rc != LuaError::OK) { | 583 | if (_rc != LuaError::OK) { |
584 | _finalizer_pushed = 1 + push_stack_trace(_L, errorTraceLevel_, _rc, lua_gettop(_L)); // _L: ... finalizers error_handler() err_msg2? trace | 584 | _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, lua_gettop(_L)); // _L: ... finalizers error_handler() err_msg2? trace |
585 | // If one finalizer fails, don't run the others. Return this | 585 | // If one finalizer fails, don't run the others. Return this |
586 | // as the 'real' error, replacing what we could have had (or not) | 586 | // as the 'real' error, replacing what we could have had (or not) |
587 | // from the actual code. | 587 | // from the actual code. |
@@ -622,35 +622,35 @@ static [[nodiscard]] int push_stack_trace(lua_State* const L_, Lane::ErrorTraceL | |||
622 | * Add the lane to selfdestruct chain; the ones still running at the end of the | 622 | * Add the lane to selfdestruct chain; the ones still running at the end of the |
623 | * whole process will be cancelled. | 623 | * whole process will be cancelled. |
624 | */ | 624 | */ |
625 | static void selfdestruct_add(Lane* lane_) | 625 | void Lane::selfdestructAdd() |
626 | { | 626 | { |
627 | std::lock_guard<std::mutex> _guard{ lane_->U->selfdestructMutex }; | 627 | std::lock_guard<std::mutex> _guard{ U->selfdestructMutex }; |
628 | assert(lane_->selfdestruct_next == nullptr); | 628 | assert(selfdestruct_next == nullptr); |
629 | 629 | ||
630 | lane_->selfdestruct_next = lane_->U->selfdestructFirst; | 630 | selfdestruct_next = U->selfdestructFirst; |
631 | lane_->U->selfdestructFirst = lane_; | 631 | U->selfdestructFirst = this; |
632 | } | 632 | } |
633 | 633 | ||
634 | // ################################################################################################# | 634 | // ################################################################################################# |
635 | 635 | ||
636 | // A free-running lane has ended; remove it from selfdestruct chain | 636 | // A free-running lane has ended; remove it from selfdestruct chain |
637 | [[nodiscard]] static bool selfdestruct_remove(Lane* lane_) | 637 | [[nodiscard]] bool Lane::selfdestructRemove() |
638 | { | 638 | { |
639 | bool _found{ false }; | 639 | bool _found{ false }; |
640 | std::lock_guard<std::mutex> _guard{ lane_->U->selfdestructMutex }; | 640 | std::lock_guard<std::mutex> _guard{ U->selfdestructMutex }; |
641 | // Make sure (within the MUTEX) that we actually are in the chain | 641 | // Make sure (within the MUTEX) that we actually are in the chain |
642 | // still (at process exit they will remove us from chain and then | 642 | // still (at process exit they will remove us from chain and then |
643 | // cancel/kill). | 643 | // cancel/kill). |
644 | // | 644 | // |
645 | if (lane_->selfdestruct_next != nullptr) { | 645 | if (selfdestruct_next != nullptr) { |
646 | Lane* volatile* _ref = static_cast<Lane* volatile*>(&lane_->U->selfdestructFirst); | 646 | Lane* volatile* _ref = static_cast<Lane* volatile*>(&U->selfdestructFirst); |
647 | 647 | ||
648 | while (*_ref != SELFDESTRUCT_END) { | 648 | while (*_ref != SELFDESTRUCT_END) { |
649 | if (*_ref == lane_) { | 649 | if (*_ref == this) { |
650 | *_ref = lane_->selfdestruct_next; | 650 | *_ref = selfdestruct_next; |
651 | lane_->selfdestruct_next = nullptr; | 651 | selfdestruct_next = nullptr; |
652 | // the terminal shutdown should wait until the lane is done with its lua_close() | 652 | // the terminal shutdown should wait until the lane is done with its lua_close() |
653 | lane_->U->selfdestructingCount.fetch_add(1, std::memory_order_release); | 653 | U->selfdestructingCount.fetch_add(1, std::memory_order_release); |
654 | _found = true; | 654 | _found = true; |
655 | break; | 655 | break; |
656 | } | 656 | } |
@@ -665,7 +665,7 @@ static void selfdestruct_add(Lane* lane_) | |||
665 | // ########################################## Main ################################################# | 665 | // ########################################## Main ################################################# |
666 | // ################################################################################################# | 666 | // ################################################################################################# |
667 | 667 | ||
668 | static void PrepareLaneHelpers(Lane* lane_) | 668 | static void PrepareLaneHelpers(Lane* const lane_) |
669 | { | 669 | { |
670 | lua_State* const _L{ lane_->L }; | 670 | lua_State* const _L{ lane_->L }; |
671 | // Tie "set_finalizer()" to the state | 671 | // Tie "set_finalizer()" to the state |
@@ -752,7 +752,7 @@ static void lane_main(Lane* const lane_) | |||
752 | } | 752 | } |
753 | 753 | ||
754 | // in case of error and if it exists, fetch stack trace from registry and push it | 754 | // in case of error and if it exists, fetch stack trace from registry and push it |
755 | lane_->nresults += push_stack_trace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] | 755 | lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] |
756 | 756 | ||
757 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); | 757 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); |
758 | // Call finalizers, if the script has set them up. | 758 | // Call finalizers, if the script has set them up. |
@@ -765,7 +765,7 @@ static void lane_main(Lane* const lane_) | |||
765 | _rc = _rc2; // we're overruling the earlier script error or normal return | 765 | _rc = _rc2; // we're overruling the earlier script error or normal return |
766 | } | 766 | } |
767 | lane_->waiting_on = nullptr; // just in case | 767 | lane_->waiting_on = nullptr; // just in case |
768 | if (selfdestruct_remove(lane_)) { // check and remove (under lock!) | 768 | if (lane_->selfdestructRemove()) { // check and remove (under lock!) |
769 | // We're a free-running thread and no-one is there to clean us up. | 769 | // We're a free-running thread and no-one is there to clean us up. |
770 | lane_->closeState(); | 770 | lane_->closeState(); |
771 | lane_->U->selfdestructMutex.lock(); | 771 | lane_->U->selfdestructMutex.lock(); |
@@ -809,7 +809,7 @@ static LUAG_FUNC(lane_close) | |||
809 | 809 | ||
810 | // ################################################################################################# | 810 | // ################################################################################################# |
811 | 811 | ||
812 | // = thread_gc( lane_ud ) | 812 | // = lane_gc( lane_ud ) |
813 | // | 813 | // |
814 | // Cleanup for a thread userdata. If the thread is still executing, leave it | 814 | // Cleanup for a thread userdata. If the thread is still executing, leave it |
815 | // alive as a free-running thread (will clean up itself). | 815 | // alive as a free-running thread (will clean up itself). |
@@ -823,7 +823,7 @@ static LUAG_FUNC(lane_close) | |||
823 | static LUAG_FUNC(lane_gc) | 823 | static LUAG_FUNC(lane_gc) |
824 | { | 824 | { |
825 | bool _have_gc_cb{ false }; | 825 | bool _have_gc_cb{ false }; |
826 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud | 826 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud |
827 | 827 | ||
828 | // if there a gc callback? | 828 | // if there a gc callback? |
829 | lua_getiuservalue(L_, 1, 1); // L_: ud uservalue | 829 | lua_getiuservalue(L_, 1, 1); // L_: ud uservalue |
@@ -840,7 +840,7 @@ static LUAG_FUNC(lane_gc) | |||
840 | // We can read 'lane->status' without locks, but not wait for it | 840 | // We can read 'lane->status' without locks, but not wait for it |
841 | if (_lane->status < Lane::Done) { | 841 | if (_lane->status < Lane::Done) { |
842 | // still running: will have to be cleaned up later | 842 | // still running: will have to be cleaned up later |
843 | selfdestruct_add(_lane); | 843 | _lane->selfdestructAdd(); |
844 | assert(_lane->selfdestruct_next); | 844 | assert(_lane->selfdestruct_next); |
845 | if (_have_gc_cb) { | 845 | if (_have_gc_cb) { |
846 | luaG_pushstring(L_, "selfdestruct"); // L_: ud gc_cb name status | 846 | luaG_pushstring(L_, "selfdestruct"); // L_: ud gc_cb name status |
@@ -174,6 +174,8 @@ class Lane | |||
174 | void pushStatusString(lua_State* L_) const; | 174 | void pushStatusString(lua_State* L_) const; |
175 | void pushIndexedResult(lua_State* L_, int key_) const; | 175 | void pushIndexedResult(lua_State* L_, int key_) const; |
176 | void resetResultsStorage(lua_State* const L_, int gc_cb_idx_); | 176 | void resetResultsStorage(lua_State* const L_, int gc_cb_idx_); |
177 | void selfdestructAdd(); | ||
178 | [[nodiscard]] bool selfdestructRemove(); | ||
177 | void securizeDebugName(lua_State* L_); | 179 | void securizeDebugName(lua_State* L_); |
178 | void startThread(int priority_); | 180 | void startThread(int priority_); |
179 | [[nodiscard]] int storeResults(lua_State* L_); | 181 | [[nodiscard]] int storeResults(lua_State* L_); |
diff --git a/src/lanes.cpp b/src/lanes.cpp index b096774..c820568 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -836,7 +836,7 @@ static void EnableCrashingOnCrashes(void) | |||
836 | 836 | ||
837 | // ################################################################################################# | 837 | // ################################################################################################# |
838 | 838 | ||
839 | LANES_API int luaopen_lanes_core(lua_State* L_) | 839 | LANES_API int luaopen_lanes_core(lua_State* const L_) |
840 | { | 840 | { |
841 | #if defined PLATFORM_WIN32 && !defined NDEBUG | 841 | #if defined PLATFORM_WIN32 && !defined NDEBUG |
842 | EnableCrashingOnCrashes(); | 842 | EnableCrashingOnCrashes(); |
@@ -879,7 +879,7 @@ LANES_API int luaopen_lanes_core(lua_State* L_) | |||
879 | 879 | ||
880 | // ################################################################################################# | 880 | // ################################################################################################# |
881 | 881 | ||
882 | [[nodiscard]] static int default_luaopen_lanes(lua_State* L_) | 882 | [[nodiscard]] static int default_luaopen_lanes(lua_State* const L_) |
883 | { | 883 | { |
884 | LuaError const _rc{ luaL_loadfile(L_, "lanes.lua") || lua_pcall(L_, 0, 1, 0) }; | 884 | LuaError const _rc{ luaL_loadfile(L_, "lanes.lua") || lua_pcall(L_, 0, 1, 0) }; |
885 | if (_rc != LuaError::OK) { | 885 | if (_rc != LuaError::OK) { |
@@ -891,7 +891,7 @@ LANES_API int luaopen_lanes_core(lua_State* L_) | |||
891 | // ################################################################################################# | 891 | // ################################################################################################# |
892 | 892 | ||
893 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application | 893 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application |
894 | LANES_API void luaopen_lanes_embedded(lua_State* L_, lua_CFunction _luaopen_lanes) | 894 | LANES_API void luaopen_lanes_embedded(lua_State* const L_, lua_CFunction const luaopen_lanes_) |
895 | { | 895 | { |
896 | STACK_CHECK_START_REL(L_, 0); | 896 | STACK_CHECK_START_REL(L_, 0); |
897 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded | 897 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded |
@@ -899,6 +899,6 @@ LANES_API void luaopen_lanes_embedded(lua_State* L_, lua_CFunction _luaopen_lane | |||
899 | lua_pop(L_, 1); // L_: ... | 899 | lua_pop(L_, 1); // L_: ... |
900 | STACK_CHECK(L_, 0); | 900 | STACK_CHECK(L_, 0); |
901 | // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it | 901 | // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it |
902 | luaL_requiref(L_, kLanesLibName, _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // L_: ... lanes | 902 | luaL_requiref(L_, kLanesLibName, luaopen_lanes_ ? luaopen_lanes_ : default_luaopen_lanes, 0); // L_: ... lanes |
903 | STACK_CHECK(L_, 1); | 903 | STACK_CHECK(L_, 1); |
904 | } | 904 | } |
diff --git a/src/lanes.h b/src/lanes.h index 925db59..a3731e4 100644 --- a/src/lanes.h +++ b/src/lanes.h | |||
@@ -12,9 +12,9 @@ | |||
12 | #define LANES_VERSION_GREATER_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR > MAJOR) || (LANES_VERSION_MAJOR == MAJOR && (LANES_VERSION_MINOR > MINOR || (LANES_VERSION_MINOR == MINOR && LANES_VERSION_PATCH > PATCH)))) | 12 | #define LANES_VERSION_GREATER_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR > MAJOR) || (LANES_VERSION_MAJOR == MAJOR && (LANES_VERSION_MINOR > MINOR || (LANES_VERSION_MINOR == MINOR && LANES_VERSION_PATCH > PATCH)))) |
13 | #define LANES_VERSION_GREATER_OR_EQUAL(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR > MAJOR) || (LANES_VERSION_MAJOR == MAJOR && (LANES_VERSION_MINOR > MINOR || (LANES_VERSION_MINOR == MINOR && LANES_VERSION_PATCH >= PATCH)))) | 13 | #define LANES_VERSION_GREATER_OR_EQUAL(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR > MAJOR) || (LANES_VERSION_MAJOR == MAJOR && (LANES_VERSION_MINOR > MINOR || (LANES_VERSION_MINOR == MINOR && LANES_VERSION_PATCH >= PATCH)))) |
14 | 14 | ||
15 | LANES_API [[nodiscard]] int luaopen_lanes_core(lua_State* L_); | 15 | LANES_API int luaopen_lanes_core(lua_State* L_); |
16 | 16 | ||
17 | // Call this to work with embedded Lanes instead of calling luaopen_lanes_core() | 17 | // Call this to work with embedded Lanes instead of calling luaopen_lanes_core() |
18 | LANES_API void luaopen_lanes_embedded(lua_State* L_, lua_CFunction _luaopen_lanes); | 18 | LANES_API void luaopen_lanes_embedded(lua_State* L_, lua_CFunction luaopen_lanes_); |
19 | using luaopen_lanes_embedded_t = void (*)(lua_State* L_, lua_CFunction luaopen_lanes_); | 19 | using luaopen_lanes_embedded_t = void (*)(lua_State* L_, lua_CFunction luaopen_lanes_); |
20 | static_assert(std::is_same_v<decltype(&luaopen_lanes_embedded), luaopen_lanes_embedded_t>, "signature changed: check all uses of luaopen_lanes_embedded_t"); | 20 | static_assert(std::is_same_v<decltype(&luaopen_lanes_embedded), luaopen_lanes_embedded_t>, "signature changed: check all uses of luaopen_lanes_embedded_t"); |