diff options
Diffstat (limited to 'src')
| -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"); |
