aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-10-24 17:36:35 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-10-24 17:36:35 +0200
commit8e33d8a2ca89d630f8890332df7e5737fc4608c8 (patch)
treeeb4ee9a8f5f1164f09438c7c40315ac63c19039d
parent0d94a88b4de3973ce99fd77c6731c8219444db9e (diff)
downloadlanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.tar.gz
lanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.tar.bz2
lanes-8e33d8a2ca89d630f8890332df7e5737fc4608c8.zip
Modernized some more trifles
-rw-r--r--src/cancel.cpp16
-rw-r--r--src/cancel.h5
-rw-r--r--src/lane.cpp12
-rw-r--r--src/lane.h21
-rw-r--r--src/state.cpp2
-rw-r--r--src/universe.cpp2
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])
142LUAG_FUNC(thread_cancel) 142LUAG_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
35inline 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
36static constexpr UniqueKey kCancelError{ 0x0630345FEF912746ull, "lanes.cancel_error" }; // 'raise_cancel_error' sentinel 41static 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
904CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) 904CancelResult 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();
diff --git a/src/lane.h b/src/lane.h
index a11b5f5..7f3cea0 100644
--- a/src/lane.h
+++ b/src/lane.h
@@ -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
47enum 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"
47class Lane 54class 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 }