diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cancel.cpp | 126 | ||||
| -rw-r--r-- | src/keeper.cpp | 26 | ||||
| -rw-r--r-- | src/keeper.hpp | 1 |
3 files changed, 89 insertions, 64 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index ec9b6e4..2d8029e 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
| @@ -38,6 +38,53 @@ THE SOFTWARE. | |||
| 38 | #include "debugspew.hpp" | 38 | #include "debugspew.hpp" |
| 39 | #include "lane.hpp" | 39 | #include "lane.hpp" |
| 40 | 40 | ||
| 41 | namespace { | ||
| 42 | namespace local { | ||
| 43 | |||
| 44 | // ######################################################################################### | ||
| 45 | // ######################################################################################### | ||
| 46 | |||
| 47 | [[nodiscard]] | ||
| 48 | static std::optional<CancelOp> WhichCancelOp(std::string_view const& opString_) | ||
| 49 | { | ||
| 50 | if (opString_ == "soft") { | ||
| 51 | return std::make_optional<CancelOp>(CancelRequest::Soft, LuaHookMask::None); | ||
| 52 | } else if (opString_ == "hard") { | ||
| 53 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::None); | ||
| 54 | } else if (opString_ == "call") { | ||
| 55 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Call); | ||
| 56 | } else if (opString_ == "ret") { | ||
| 57 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Ret); | ||
| 58 | } else if (opString_ == "line") { | ||
| 59 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Line); | ||
| 60 | } else if (opString_ == "count") { | ||
| 61 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Count); | ||
| 62 | } else if (opString_ == "all") { | ||
| 63 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::All); | ||
| 64 | } | ||
| 65 | return std::nullopt; | ||
| 66 | } | ||
| 67 | |||
| 68 | // ######################################################################################### | ||
| 69 | |||
| 70 | [[nodiscard]] | ||
| 71 | static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_) | ||
| 72 | { | ||
| 73 | if (luaG_type(L_, idx_) == LuaType::STRING) { | ||
| 74 | std::string_view const _str{ luaG_tostring(L_, idx_) }; | ||
| 75 | auto const _op{ WhichCancelOp(_str) }; | ||
| 76 | lua_remove(L_, idx_); // argument is processed, remove it | ||
| 77 | if (!_op.has_value()) { | ||
| 78 | raise_luaL_error(L_, "Invalid cancel operation '%s'", _str.data()); | ||
| 79 | } | ||
| 80 | return _op.value(); | ||
| 81 | } | ||
| 82 | return CancelOp{ CancelRequest::Hard, LuaHookMask::None }; | ||
| 83 | } | ||
| 84 | |||
| 85 | } // namespace local | ||
| 86 | } // namespace | ||
| 87 | |||
| 41 | // ################################################################################################# | 88 | // ################################################################################################# |
| 42 | // ################################################################################################# | 89 | // ################################################################################################# |
| 43 | 90 | ||
| @@ -60,66 +107,6 @@ CancelRequest CheckCancelRequest(lua_State* const L_) | |||
| 60 | 107 | ||
| 61 | // ################################################################################################# | 108 | // ################################################################################################# |
| 62 | // ################################################################################################# | 109 | // ################################################################################################# |
| 63 | |||
| 64 | //--- | ||
| 65 | // = lane_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] ) | ||
| 66 | // | ||
| 67 | // The originator thread asking us specifically to cancel the other thread. | ||
| 68 | // | ||
| 69 | // 'timeout': <0: wait forever, until the lane is finished | ||
| 70 | // 0.0: just signal it to cancel, no time waited | ||
| 71 | // >0: time to wait for the lane to detect cancellation | ||
| 72 | // | ||
| 73 | // 'wake_lindas_bool': if true, signal any linda the thread is waiting on | ||
| 74 | // instead of waiting for its timeout (if any) | ||
| 75 | // | ||
| 76 | // Returns: true if the lane was already finished (Done/Error/Cancelled) or if we | ||
| 77 | // managed to cancel it. | ||
| 78 | // false if the cancellation timed out, or a kill was needed. | ||
| 79 | // | ||
| 80 | |||
| 81 | // ################################################################################################# | ||
| 82 | // ################################################################################################# | ||
| 83 | |||
| 84 | static std::optional<CancelOp> WhichCancelOp(std::string_view const& opString_) | ||
| 85 | { | ||
| 86 | if (opString_ == "soft") { | ||
| 87 | return std::make_optional<CancelOp>(CancelRequest::Soft, LuaHookMask::None); | ||
| 88 | } else if (opString_ == "hard") { | ||
| 89 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::None); | ||
| 90 | } else if (opString_== "call") { | ||
| 91 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Call); | ||
| 92 | } else if (opString_ == "ret") { | ||
| 93 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Ret); | ||
| 94 | } else if (opString_ == "line") { | ||
| 95 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Line); | ||
| 96 | } else if (opString_ == "count") { | ||
| 97 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Count); | ||
| 98 | } else if (opString_ == "all") { | ||
| 99 | return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::All); | ||
| 100 | } | ||
| 101 | return std::nullopt; | ||
| 102 | } | ||
| 103 | |||
| 104 | // ################################################################################################# | ||
| 105 | |||
| 106 | [[nodiscard]] | ||
| 107 | static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_) | ||
| 108 | { | ||
| 109 | if (luaG_type(L_, idx_) == LuaType::STRING) { | ||
| 110 | std::string_view const _str{ luaG_tostring(L_, idx_) }; | ||
| 111 | auto const _op{ WhichCancelOp(_str) }; | ||
| 112 | lua_remove(L_, idx_); // argument is processed, remove it | ||
| 113 | if (!_op.has_value()) { | ||
| 114 | raise_luaL_error(L_, "Invalid cancel operation '%s'", _str.data()); | ||
| 115 | } | ||
| 116 | return _op.value(); | ||
| 117 | } | ||
| 118 | return CancelOp{ CancelRequest::Hard, LuaHookMask::None }; | ||
| 119 | } | ||
| 120 | |||
| 121 | // ################################################################################################# | ||
| 122 | // ################################################################################################# | ||
| 123 | // ######################################### Lua API ############################################### | 110 | // ######################################### Lua API ############################################### |
| 124 | // ################################################################################################# | 111 | // ################################################################################################# |
| 125 | // ################################################################################################# | 112 | // ################################################################################################# |
| @@ -143,11 +130,28 @@ LUAG_FUNC(cancel_test) | |||
| 143 | 130 | ||
| 144 | // ################################################################################################# | 131 | // ################################################################################################# |
| 145 | 132 | ||
| 133 | //--- | ||
| 134 | // = lane_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] ) | ||
| 135 | // | ||
| 136 | // The originator thread asking us specifically to cancel the other thread. | ||
| 137 | // | ||
| 138 | // 'timeout': <0: wait forever, until the lane is finished | ||
| 139 | // 0.0: just signal it to cancel, no time waited | ||
| 140 | // >0: time to wait for the lane to detect cancellation | ||
| 141 | // | ||
| 142 | // 'wake_lindas_bool': if true, signal any linda the thread is waiting on | ||
| 143 | // instead of waiting for its timeout (if any) | ||
| 144 | // | ||
| 145 | // Returns: true if the lane was already finished (Done/Error/Cancelled) or if we | ||
| 146 | // managed to cancel it. | ||
| 147 | // false if the cancellation timed out, or a kill was needed. | ||
| 148 | // | ||
| 149 | |||
| 146 | // bool[,reason] = lane_h:cancel( [cancel_op, hookcount] [, timeout] [, wake_lane]) | 150 | // bool[,reason] = lane_h:cancel( [cancel_op, hookcount] [, timeout] [, wake_lane]) |
| 147 | LUAG_FUNC(lane_cancel) | 151 | LUAG_FUNC(lane_cancel) |
| 148 | { | 152 | { |
| 149 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane [cancel_op, hookcount] [, timeout] [, wake_lane] | 153 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane [cancel_op, hookcount] [, timeout] [, wake_lane] |
| 150 | CancelOp const _op{ WhichCancelOp(L_, StackIndex{ 2 }) }; // L_: lane [hookcount] [, timeout] [, wake_lane] | 154 | CancelOp const _op{ local::WhichCancelOp(L_, StackIndex{ 2 }) }; // L_: lane [hookcount] [, timeout] [, wake_lane] |
| 151 | 155 | ||
| 152 | int const _hook_count{ std::invoke([_op, L_]() { | 156 | int const _hook_count{ std::invoke([_op, L_]() { |
| 153 | if (_op.hookMask == LuaHookMask::None) { | 157 | if (_op.hookMask == LuaHookMask::None) { |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 7619eb4..2e13de3 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
| @@ -104,6 +104,7 @@ class KeyUD final | |||
| 104 | 104 | ||
| 105 | // ################################################################################################# | 105 | // ################################################################################################# |
| 106 | 106 | ||
| 107 | [[nodiscard]] | ||
| 107 | bool KeyUD::changeLimit(LindaLimit const limit_) | 108 | bool KeyUD::changeLimit(LindaLimit const limit_) |
| 108 | { | 109 | { |
| 109 | bool const _newSlackAvailable{ | 110 | bool const _newSlackAvailable{ |
| @@ -127,6 +128,7 @@ LindaRestrict KeyUD::changeRestrict(LindaRestrict const restrict_) | |||
| 127 | 128 | ||
| 128 | // in: nothing | 129 | // in: nothing |
| 129 | // out: { first = 1, count = 0, limit = -1} | 130 | // out: { first = 1, count = 0, limit = -1} |
| 131 | [[nodiscard]] | ||
| 130 | KeyUD* KeyUD::Create(KeeperState const K_) | 132 | KeyUD* KeyUD::Create(KeeperState const K_) |
| 131 | { | 133 | { |
| 132 | STACK_GROW(K_, 2); | 134 | STACK_GROW(K_, 2); |
| @@ -141,6 +143,7 @@ KeyUD* KeyUD::Create(KeeperState const K_) | |||
| 141 | 143 | ||
| 142 | // ################################################################################################# | 144 | // ################################################################################################# |
| 143 | 145 | ||
| 146 | [[nodiscard]] | ||
| 144 | KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_) | 147 | KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_) |
| 145 | { | 148 | { |
| 146 | return luaG_tofulluserdata<KeyUD>(K_, idx_); | 149 | return luaG_tofulluserdata<KeyUD>(K_, idx_); |
| @@ -181,6 +184,7 @@ void KeyUD::peek(KeeperState const K_, int const count_) const | |||
| 181 | 184 | ||
| 182 | // in: fifo | 185 | // in: fifo |
| 183 | // out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) | 186 | // out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
| 187 | [[nodiscard]] | ||
| 184 | int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | 188 | int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) |
| 185 | { | 189 | { |
| 186 | if (count < minCount_) { | 190 | if (count < minCount_) { |
| @@ -243,6 +247,7 @@ void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const | |||
| 243 | 247 | ||
| 244 | // in: expect this val... on top of the stack | 248 | // in: expect this val... on top of the stack |
| 245 | // out: nothing, removes all pushed values from the stack | 249 | // out: nothing, removes all pushed values from the stack |
| 250 | [[nodiscard]] | ||
| 246 | bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) | 251 | bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) |
| 247 | { | 252 | { |
| 248 | StackIndex const _fifoIdx{ luaG_absindex(K_, StackIndex{ -1 - count_ }) }; | 253 | StackIndex const _fifoIdx{ luaG_absindex(K_, StackIndex{ -1 - count_ }) }; |
| @@ -272,7 +277,7 @@ void KeyUD::pushFillStatus(KeeperState const K_) const | |||
| 272 | luaG_pushstring(K_, kUnder); | 277 | luaG_pushstring(K_, kUnder); |
| 273 | return; | 278 | return; |
| 274 | } | 279 | } |
| 275 | int const _delta{limit - count}; | 280 | int const _delta{ limit - count }; |
| 276 | if (_delta < 0) { | 281 | if (_delta < 0) { |
| 277 | luaG_pushstring(K_, kOver); | 282 | luaG_pushstring(K_, kOver); |
| 278 | } else if (_delta > 0) { | 283 | } else if (_delta > 0) { |
| @@ -295,7 +300,10 @@ void KeyUD::PushFillStatus(KeeperState const K_, KeyUD const* const key_) | |||
| 295 | 300 | ||
| 296 | // ################################################################################################# | 301 | // ################################################################################################# |
| 297 | 302 | ||
| 298 | // expects 'this' on top of the stack | 303 | // in: expects 'this' on top of the stack |
| 304 | // out: nothing | ||
| 305 | // returns true if the channel was full | ||
| 306 | [[nodiscard]] | ||
| 299 | bool KeyUD::reset(KeeperState const K_) | 307 | bool KeyUD::reset(KeeperState const K_) |
| 300 | { | 308 | { |
| 301 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); | 309 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); |
| @@ -347,6 +355,7 @@ static void PushKeysDB(KeeperState const K_, StackIndex const idx_) | |||
| 347 | 355 | ||
| 348 | // in: linda | 356 | // in: linda |
| 349 | // out: nothing | 357 | // out: nothing |
| 358 | [[nodiscard]] | ||
| 350 | int keepercall_collectgarbage(lua_State* const L_) | 359 | int keepercall_collectgarbage(lua_State* const L_) |
| 351 | { | 360 | { |
| 352 | lua_gc(L_, LUA_GCCOLLECT, 0); | 361 | lua_gc(L_, LUA_GCCOLLECT, 0); |
| @@ -356,6 +365,7 @@ int keepercall_collectgarbage(lua_State* const L_) | |||
| 356 | // ################################################################################################# | 365 | // ################################################################################################# |
| 357 | 366 | ||
| 358 | // in: linda [, key [, ...]] | 367 | // in: linda [, key [, ...]] |
| 368 | [[nodiscard]] | ||
| 359 | int keepercall_count(lua_State* const L_) | 369 | int keepercall_count(lua_State* const L_) |
| 360 | { | 370 | { |
| 361 | KeeperState const _K{ L_ }; | 371 | KeeperState const _K{ L_ }; |
| @@ -419,6 +429,7 @@ int keepercall_count(lua_State* const L_) | |||
| 419 | 429 | ||
| 420 | // in: linda | 430 | // in: linda |
| 421 | // not part of the linda public API, only used for cleanup at linda GC | 431 | // not part of the linda public API, only used for cleanup at linda GC |
| 432 | [[nodiscard]] | ||
| 422 | int keepercall_destruct(lua_State* const L_) | 433 | int keepercall_destruct(lua_State* const L_) |
| 423 | { | 434 | { |
| 424 | STACK_GROW(L_, 3); | 435 | STACK_GROW(L_, 3); |
| @@ -437,6 +448,7 @@ int keepercall_destruct(lua_State* const L_) | |||
| 437 | 448 | ||
| 438 | // in: linda_ud key [count] | 449 | // in: linda_ud key [count] |
| 439 | // out: N <N values>|kRestrictedChannel | 450 | // out: N <N values>|kRestrictedChannel |
| 451 | [[nodiscard]] | ||
| 440 | int keepercall_get(lua_State* const L_) | 452 | int keepercall_get(lua_State* const L_) |
| 441 | { | 453 | { |
| 442 | KeeperState const _K{ L_ }; | 454 | KeeperState const _K{ L_ }; |
| @@ -471,6 +483,7 @@ int keepercall_get(lua_State* const L_) | |||
| 471 | 483 | ||
| 472 | // in: linda key [n|nil] | 484 | // in: linda key [n|nil] |
| 473 | // out: boolean, <fill status: string> | 485 | // out: boolean, <fill status: string> |
| 486 | [[nodiscard]] | ||
| 474 | int keepercall_limit(lua_State* const L_) | 487 | int keepercall_limit(lua_State* const L_) |
| 475 | { | 488 | { |
| 476 | KeeperState const _K{ L_ }; | 489 | KeeperState const _K{ L_ }; |
| @@ -514,6 +527,7 @@ int keepercall_limit(lua_State* const L_) | |||
| 514 | 527 | ||
| 515 | // in: linda, key [, key]? | 528 | // in: linda, key [, key]? |
| 516 | // out: (key, val) or nothing | 529 | // out: (key, val) or nothing |
| 530 | [[nodiscard]] | ||
| 517 | int keepercall_receive(lua_State* const L_) | 531 | int keepercall_receive(lua_State* const L_) |
| 518 | { | 532 | { |
| 519 | KeeperState const _K{ L_ }; | 533 | KeeperState const _K{ L_ }; |
| @@ -558,6 +572,7 @@ int keepercall_receive(lua_State* const L_) | |||
| 558 | // ################################################################################################# | 572 | // ################################################################################################# |
| 559 | 573 | ||
| 560 | // in: linda key mincount [maxcount] | 574 | // in: linda key mincount [maxcount] |
| 575 | [[nodiscard]] | ||
| 561 | int keepercall_receive_batched(lua_State* const L_) | 576 | int keepercall_receive_batched(lua_State* const L_) |
| 562 | { | 577 | { |
| 563 | KeeperState const _K{ L_ }; | 578 | KeeperState const _K{ L_ }; |
| @@ -591,6 +606,7 @@ int keepercall_receive_batched(lua_State* const L_) | |||
| 591 | 606 | ||
| 592 | // in: linda key [mode] | 607 | // in: linda key [mode] |
| 593 | // out: mode | 608 | // out: mode |
| 609 | [[nodiscard]] | ||
| 594 | int keepercall_restrict(lua_State* const L_) | 610 | int keepercall_restrict(lua_State* const L_) |
| 595 | { | 611 | { |
| 596 | KeeperState const _K{ L_ }; | 612 | KeeperState const _K{ L_ }; |
| @@ -655,6 +671,7 @@ int keepercall_restrict(lua_State* const L_) | |||
| 655 | 671 | ||
| 656 | // in: linda, key, ... | 672 | // in: linda, key, ... |
| 657 | // out: true|false|kRestrictedChannel | 673 | // out: true|false|kRestrictedChannel |
| 674 | [[nodiscard]] | ||
| 658 | int keepercall_send(lua_State* const L_) | 675 | int keepercall_send(lua_State* const L_) |
| 659 | { | 676 | { |
| 660 | KeeperState const _K{ L_ }; | 677 | KeeperState const _K{ L_ }; |
| @@ -694,6 +711,7 @@ int keepercall_send(lua_State* const L_) | |||
| 694 | 711 | ||
| 695 | // in: linda key [val...] | 712 | // in: linda key [val...] |
| 696 | // out: true if the linda was full but it's no longer the case, else false, or kRestrictedChannel if the key is restricted | 713 | // out: true if the linda was full but it's no longer the case, else false, or kRestrictedChannel if the key is restricted |
| 714 | [[nodiscard]] | ||
| 697 | int keepercall_set(lua_State* const L_) | 715 | int keepercall_set(lua_State* const L_) |
| 698 | { | 716 | { |
| 699 | KeeperState const _K{ L_ }; | 717 | KeeperState const _K{ L_ }; |
| @@ -763,6 +781,7 @@ int keepercall_set(lua_State* const L_) | |||
| 763 | * | 781 | * |
| 764 | * Returns: number of return values (pushed to 'L'), unset in case of error | 782 | * Returns: number of return values (pushed to 'L'), unset in case of error |
| 765 | */ | 783 | */ |
| 784 | [[nodiscard]] | ||
| 766 | KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_) | 785 | KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_) |
| 767 | { | 786 | { |
| 768 | KeeperCallResult _result; | 787 | KeeperCallResult _result; |
| @@ -832,6 +851,7 @@ KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua | |||
| 832 | // } | 851 | // } |
| 833 | // ... | 852 | // ... |
| 834 | // } | 853 | // } |
| 854 | [[nodiscard]] | ||
| 835 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | 855 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) |
| 836 | { | 856 | { |
| 837 | Keeper* const _keeper{ linda_.whichKeeper() }; | 857 | Keeper* const _keeper{ linda_.whichKeeper() }; |
| @@ -961,7 +981,7 @@ void Keepers::collectGarbage() | |||
| 961 | 981 | ||
| 962 | // ################################################################################################# | 982 | // ################################################################################################# |
| 963 | 983 | ||
| 964 | 984 | [[nodiscard]] | |
| 965 | bool Keepers::close() | 985 | bool Keepers::close() |
| 966 | { | 986 | { |
| 967 | if (isClosing.test_and_set(std::memory_order_release)) { | 987 | if (isClosing.test_and_set(std::memory_order_release)) { |
diff --git a/src/keeper.hpp b/src/keeper.hpp index 0aa44f2..955577c 100644 --- a/src/keeper.hpp +++ b/src/keeper.hpp | |||
| @@ -68,6 +68,7 @@ struct Keepers | |||
| 68 | 68 | ||
| 69 | Keepers() = default; | 69 | Keepers() = default; |
| 70 | void collectGarbage(); | 70 | void collectGarbage(); |
| 71 | [[nodiscard]] | ||
| 71 | bool close(); | 72 | bool close(); |
| 72 | [[nodiscard]] | 73 | [[nodiscard]] |
| 73 | Keeper* getKeeper(KeeperIndex idx_); | 74 | Keeper* getKeeper(KeeperIndex idx_); |
