diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-24 17:36:35 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-24 17:36:35 +0200 |
commit | 8e33d8a2ca89d630f8890332df7e5737fc4608c8 (patch) | |
tree | eb4ee9a8f5f1164f09438c7c40315ac63c19039d | |
parent | 0d94a88b4de3973ce99fd77c6731c8219444db9e (diff) | |
download | lanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.tar.gz lanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.tar.bz2 lanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.zip |
Modernized some more trifles
-rw-r--r-- | src/cancel.cpp | 16 | ||||
-rw-r--r-- | src/cancel.h | 5 | ||||
-rw-r--r-- | src/lane.cpp | 12 | ||||
-rw-r--r-- | src/lane.h | 21 | ||||
-rw-r--r-- | src/state.cpp | 2 | ||||
-rw-r--r-- | src/universe.cpp | 2 |
6 files changed, 38 insertions, 20 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index b14dca6..2d0b807 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -138,14 +138,14 @@ LUAG_FUNC(cancel_test) | |||
138 | 138 | ||
139 | // ################################################################################################# | 139 | // ################################################################################################# |
140 | 140 | ||
141 | // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, wake_lane]) | 141 | // bool[,reason] = lane_h:cancel( [cancel_op, hookcount] [, timeout] [, wake_lane]) |
142 | LUAG_FUNC(thread_cancel) | 142 | LUAG_FUNC(thread_cancel) |
143 | { | 143 | { |
144 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; | 144 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
145 | CancelOp const _op{ WhichCancelOp(L_, StackIndex{ 2 }) }; // this removes the op string from the stack | 145 | CancelOp const _op{ WhichCancelOp(L_, StackIndex{ 2 }) }; // this removes the cancel_op string from the stack |
146 | 146 | ||
147 | int _hook_count{ 0 }; | 147 | int _hook_count{ 0 }; |
148 | if (static_cast<int>(_op) > static_cast<int>(CancelOp::Soft)) { // hook is requested | 148 | if (_op > CancelOp::Soft) { // hook is requested |
149 | _hook_count = static_cast<int>(luaL_checkinteger(L_, 2)); | 149 | _hook_count = static_cast<int>(luaL_checkinteger(L_, 2)); |
150 | lua_remove(L_, 2); // argument is processed, remove it | 150 | lua_remove(L_, 2); // argument is processed, remove it |
151 | if (_hook_count < 1) { | 151 | if (_hook_count < 1) { |
@@ -167,23 +167,23 @@ LUAG_FUNC(thread_cancel) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | // we wake by default in "hard" mode (remember that hook is hard too), but this can be turned off if desired | 169 | // we wake by default in "hard" mode (remember that hook is hard too), but this can be turned off if desired |
170 | bool _wake_lane{ _op != CancelOp::Soft }; | 170 | WakeLane _wake_lane{ _op != CancelOp::Soft ? WakeLane::Yes : WakeLane::No }; |
171 | if (lua_gettop(L_) >= 2) { | 171 | if (lua_gettop(L_) >= 2) { |
172 | if (!lua_isboolean(L_, 2)) { | 172 | if (!lua_isboolean(L_, 2)) { |
173 | raise_luaL_error(L_, "wake_lindas argument is not a boolean"); | 173 | raise_luaL_error(L_, "wake_lane argument is not a boolean"); |
174 | } | 174 | } |
175 | _wake_lane = lua_toboolean(L_, 2) ? true : false; | 175 | _wake_lane = lua_toboolean(L_, 2) ? WakeLane::Yes : WakeLane::No; |
176 | lua_remove(L_, 2); // argument is processed, remove it | 176 | lua_remove(L_, 2); // argument is processed, remove it |
177 | } | 177 | } |
178 | STACK_CHECK_START_REL(L_, 0); | 178 | STACK_CHECK_START_REL(L_, 0); |
179 | switch (_lane->cancel(_op, _hook_count, _until, _wake_lane)) { | 179 | switch (_lane->cancel(_op, _until, _wake_lane, _hook_count)) { |
180 | default: // should never happen unless we added a case and forgot to handle it | 180 | default: // should never happen unless we added a case and forgot to handle it |
181 | raise_luaL_error(L_, "should not get here!"); | 181 | raise_luaL_error(L_, "should not get here!"); |
182 | break; | 182 | break; |
183 | 183 | ||
184 | case CancelResult::Timeout: | 184 | case CancelResult::Timeout: |
185 | lua_pushboolean(L_, 0); // false | 185 | lua_pushboolean(L_, 0); // false |
186 | lua_pushstring(L_, "timeout"); // false "timeout" | 186 | luaG_pushstring(L_, "timeout"); // false "timeout" |
187 | break; | 187 | break; |
188 | 188 | ||
189 | case CancelResult::Cancelled: | 189 | case CancelResult::Cancelled: |
diff --git a/src/cancel.h b/src/cancel.h index e62cf0a..6dbea99 100644 --- a/src/cancel.h +++ b/src/cancel.h | |||
@@ -32,6 +32,11 @@ enum class CancelOp | |||
32 | MaskAll = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT | 32 | MaskAll = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT |
33 | }; | 33 | }; |
34 | 34 | ||
35 | inline auto operator<=>(CancelOp const a_, CancelOp const b_) | ||
36 | { | ||
37 | return static_cast<std::underlying_type_t<CancelOp>>(a_) <=> static_cast<std::underlying_type_t<CancelOp>>(b_); | ||
38 | } | ||
39 | |||
35 | // xxh64 of string "kCancelError" generated at https://www.pelock.com/products/hash-calculator | 40 | // xxh64 of string "kCancelError" generated at https://www.pelock.com/products/hash-calculator |
36 | static constexpr UniqueKey kCancelError{ 0x0630345FEF912746ull, "lanes.cancel_error" }; // 'raise_cancel_error' sentinel | 41 | static constexpr UniqueKey kCancelError{ 0x0630345FEF912746ull, "lanes.cancel_error" }; // 'raise_cancel_error' sentinel |
37 | 42 | ||
diff --git a/src/lane.cpp b/src/lane.cpp index e88a213..9f68c91 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -901,7 +901,7 @@ Lane::~Lane() | |||
901 | 901 | ||
902 | // ################################################################################################# | 902 | // ################################################################################################# |
903 | 903 | ||
904 | CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) | 904 | CancelResult Lane::cancel(CancelOp const op_, std::chrono::time_point<std::chrono::steady_clock> const until_, WakeLane const wakeLane_, int const hookCount_) |
905 | { | 905 | { |
906 | // this is a hook installed with lua_sethook: can't capture anything to be convertible to lua_Hook | 906 | // this is a hook installed with lua_sethook: can't capture anything to be convertible to lua_Hook |
907 | static constexpr lua_Hook _cancelHook{ | 907 | static constexpr lua_Hook _cancelHook{ |
@@ -915,17 +915,17 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
915 | }; | 915 | }; |
916 | 916 | ||
917 | // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here | 917 | // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here |
918 | // We can read 'lane_->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) | 918 | // We can read status without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) |
919 | if (status >= Lane::Done) { | 919 | if (status >= Lane::Done) { |
920 | // say "ok" by default, including when lane is already done | 920 | // say "ok" by default, including when lane is already done |
921 | return CancelResult::Cancelled; | 921 | return CancelResult::Cancelled; |
922 | } | 922 | } |
923 | 923 | ||
924 | // signal the linda the wake up the thread so that it can react to the cancel query | 924 | // signal the linda to wake up the thread so that it can react to the cancel query |
925 | // let us hope we never land here with a pointer on a linda that has been destroyed... | 925 | // let us hope we never land here with a pointer on a linda that has been destroyed... |
926 | if (op_ == CancelOp::Soft) { | 926 | if (op_ == CancelOp::Soft) { |
927 | return internalCancel(CancelRequest::Soft, until_, wakeLane_); | 927 | return internalCancel(CancelRequest::Soft, until_, wakeLane_); |
928 | } else if (static_cast<int>(op_) > static_cast<int>(CancelOp::Soft)) { | 928 | } else if (op_ > CancelOp::Soft) { |
929 | lua_sethook(L, _cancelHook, static_cast<int>(op_), hookCount_); | 929 | lua_sethook(L, _cancelHook, static_cast<int>(op_), hookCount_); |
930 | } | 930 | } |
931 | 931 | ||
@@ -934,13 +934,13 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
934 | 934 | ||
935 | // ################################################################################################# | 935 | // ################################################################################################# |
936 | 936 | ||
937 | [[nodiscard]] CancelResult Lane::internalCancel(CancelRequest const rq_, std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) | 937 | [[nodiscard]] CancelResult Lane::internalCancel(CancelRequest const rq_, std::chrono::time_point<std::chrono::steady_clock> const until_, WakeLane const wakeLane_) |
938 | { | 938 | { |
939 | cancelRequest = rq_; // it's now signaled to stop | 939 | cancelRequest = rq_; // it's now signaled to stop |
940 | if (rq_ == CancelRequest::Hard) { | 940 | if (rq_ == CancelRequest::Hard) { |
941 | // lane_->thread.get_stop_source().request_stop(); | 941 | // lane_->thread.get_stop_source().request_stop(); |
942 | } | 942 | } |
943 | if (wakeLane_) { // wake the thread so that execution returns from any pending linda operation if desired | 943 | if (wakeLane_ == WakeLane::Yes) { // wake the thread so that execution returns from any pending linda operation if desired |
944 | std::condition_variable* const _waiting_on{ waiting_on }; | 944 | std::condition_variable* const _waiting_on{ waiting_on }; |
945 | if (status == Lane::Waiting && _waiting_on != nullptr) { | 945 | if (status == Lane::Waiting && _waiting_on != nullptr) { |
946 | _waiting_on->notify_all(); | 946 | _waiting_on->notify_all(); |
@@ -43,6 +43,13 @@ static constexpr std::string_view kLaneMetatableName{ "Lane" }; | |||
43 | #define kLanesLibName "lanes" | 43 | #define kLanesLibName "lanes" |
44 | #define kLanesCoreLibName kLanesLibName ".core" | 44 | #define kLanesCoreLibName kLanesLibName ".core" |
45 | 45 | ||
46 | // for cancel() argument | ||
47 | enum class WakeLane | ||
48 | { | ||
49 | No, | ||
50 | Yes | ||
51 | }; | ||
52 | |||
46 | // NOTE: values to be changed by either thread, during execution, without locking, are marked "volatile" | 53 | // NOTE: values to be changed by either thread, during execution, without locking, are marked "volatile" |
47 | class Lane | 54 | class Lane |
48 | { | 55 | { |
@@ -136,20 +143,26 @@ class Lane | |||
136 | // this one is for us, to make sure memory is freed by the correct allocator | 143 | // this one is for us, to make sure memory is freed by the correct allocator |
137 | static void operator delete(void* p_) { static_cast<Lane*>(p_)->U->internalAllocator.free(p_, sizeof(Lane)); } | 144 | static void operator delete(void* p_) { static_cast<Lane*>(p_)->U->internalAllocator.free(p_, sizeof(Lane)); } |
138 | 145 | ||
139 | Lane(Universe* U_, lua_State* L_, ErrorTraceLevel errorTraceLevel_, bool asCoroutine_); | ||
140 | ~Lane(); | 146 | ~Lane(); |
147 | Lane(Universe* U_, lua_State* L_, ErrorTraceLevel errorTraceLevel_, bool asCoroutine_); | ||
148 | |||
149 | // rule of 5 | ||
150 | Lane(Lane const&) = delete; | ||
151 | Lane(Lane&&) = delete; | ||
152 | Lane& operator=(Lane const&) = delete; | ||
153 | Lane& operator=(Lane&&) = delete; | ||
141 | 154 | ||
142 | private: | 155 | private: |
143 | 156 | ||
144 | [[nodiscard]] CancelResult internalCancel(CancelRequest rq_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); | 157 | [[nodiscard]] CancelResult internalCancel(CancelRequest rq_, std::chrono::time_point<std::chrono::steady_clock> until_, WakeLane wakeLane_); |
145 | 158 | ||
146 | public: | 159 | public: |
147 | 160 | ||
148 | CancelResult cancel(CancelOp op_, int hookCount_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); | 161 | CancelResult cancel(CancelOp op_, std::chrono::time_point<std::chrono::steady_clock> until_, WakeLane wakeLane_, int hookCount_); |
149 | void changeDebugName(StackIndex nameIdx_); | 162 | void changeDebugName(StackIndex nameIdx_); |
150 | void closeState() | 163 | void closeState() |
151 | { | 164 | { |
152 | lua_State* _L{ S }; | 165 | lua_State* const _L{ S }; |
153 | S = nullptr; | 166 | S = nullptr; |
154 | L = nullptr; | 167 | L = nullptr; |
155 | nresults = 0; | 168 | nresults = 0; |
diff --git a/src/state.cpp b/src/state.cpp index 27e595c..2e551ed 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -239,7 +239,7 @@ namespace state { | |||
239 | lua_pop(_L, 1); | 239 | lua_pop(_L, 1); |
240 | } else { | 240 | } else { |
241 | lua_pushcfunction(_L, luaopen_base); | 241 | lua_pushcfunction(_L, luaopen_base); |
242 | lua_pushstring(_L, ""); | 242 | luaG_pushstring(_L, ""); |
243 | lua_call(_L, 1, 0); | 243 | lua_call(_L, 1, 0); |
244 | } | 244 | } |
245 | } | 245 | } |
diff --git a/src/universe.cpp b/src/universe.cpp index 7630e9c..5ee2255 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -362,7 +362,7 @@ bool Universe::terminateFreeRunningLanes(lua_Duration const shutdownTimeout_, Ca | |||
362 | // if waiting on a linda, they will raise a cancel_error. | 362 | // if waiting on a linda, they will raise a cancel_error. |
363 | // if a cancellation hook is desired, it will be installed to try to raise an error | 363 | // if a cancellation hook is desired, it will be installed to try to raise an error |
364 | if (_lane->thread.joinable()) { | 364 | if (_lane->thread.joinable()) { |
365 | std::ignore = _lane->cancel(op_, 1, std::chrono::steady_clock::now() + 1us, true); | 365 | std::ignore = _lane->cancel(op_, std::chrono::steady_clock::now() + 1us, WakeLane::Yes, 1); |
366 | } | 366 | } |
367 | _lane = _lane->selfdestruct_next; | 367 | _lane = _lane->selfdestruct_next; |
368 | } | 368 | } |