aboutsummaryrefslogtreecommitdiff
path: root/src/cancel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cancel.cpp')
-rw-r--r--src/cancel.cpp86
1 files changed, 33 insertions, 53 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp
index 82c6def..e80c0b5 100644
--- a/src/cancel.cpp
+++ b/src/cancel.cpp
@@ -43,14 +43,14 @@ THE SOFTWARE.
43// ################################################################################################# 43// #################################################################################################
44 44
45/* 45/*
46* Check if the thread in question ('L') has been signalled for cancel. 46 * Check if the thread in question ('L') has been signalled for cancel.
47* 47 *
48* Called by cancellation hooks and/or pending Linda operations (because then 48 * Called by cancellation hooks and/or pending Linda operations (because then
49* the check won't affect performance). 49 * the check won't affect performance).
50* 50 *
51* Returns CANCEL_SOFT/HARD if any locks are to be exited, and 'raise_cancel_error()' called, 51 * Returns CANCEL_SOFT/HARD if any locks are to be exited, and 'raise_cancel_error()' called,
52* to make execution of the lane end. 52 * to make execution of the lane end.
53*/ 53 */
54[[nodiscard]] static inline CancelRequest cancel_test(lua_State* L_) 54[[nodiscard]] static inline CancelRequest cancel_test(lua_State* L_)
55{ 55{
56 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; 56 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) };
@@ -76,11 +76,10 @@ LUAG_FUNC(cancel_test)
76// ################################################################################################# 76// #################################################################################################
77// ################################################################################################# 77// #################################################################################################
78 78
79[[nodiscard]] static void cancel_hook(lua_State* L_, [[maybe_unused]] lua_Debug* ar) 79[[nodiscard]] static void cancel_hook(lua_State* L_, [[maybe_unused]] lua_Debug* ar_)
80{ 80{
81 DEBUGSPEW_CODE(fprintf(stderr, "cancel_hook\n")); 81 DEBUGSPEW_CODE(fprintf(stderr, "cancel_hook\n"));
82 if (cancel_test(L_) != CancelRequest::None) 82 if (cancel_test(L_) != CancelRequest::None) {
83 {
84 lua_sethook(L_, nullptr, 0, 0); 83 lua_sethook(L_, nullptr, 0, 0);
85 raise_cancel_error(L_); 84 raise_cancel_error(L_);
86 } 85 }
@@ -108,15 +107,14 @@ LUAG_FUNC(cancel_test)
108 107
109// ################################################################################################# 108// #################################################################################################
110 109
111[[nodiscard]] static CancelResult thread_cancel_soft(Lane* lane_, lua_Duration duration_, bool wake_lane_) 110[[nodiscard]] static CancelResult thread_cancel_soft(Lane* lane_, lua_Duration duration_, bool wakeLane_)
112{ 111{
113 lane_->cancel_request = CancelRequest::Soft; // it's now signaled to stop 112 lane_->cancel_request = CancelRequest::Soft; // it's now signaled to stop
114 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own 113 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own
115 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired 114 if (wakeLane_) // wake the thread so that execution returns from any pending linda operation if desired
116 { 115 {
117 std::condition_variable* const waiting_on{ lane_->m_waiting_on }; 116 std::condition_variable* const waiting_on{ lane_->m_waiting_on };
118 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr) 117 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr) {
119 {
120 waiting_on->notify_all(); 118 waiting_on->notify_all();
121 } 119 }
122 } 120 }
@@ -126,15 +124,14 @@ LUAG_FUNC(cancel_test)
126 124
127// ################################################################################################# 125// #################################################################################################
128 126
129[[nodiscard]] static CancelResult thread_cancel_hard(Lane* lane_, lua_Duration duration_, bool wake_lane_) 127[[nodiscard]] static CancelResult thread_cancel_hard(Lane* lane_, lua_Duration duration_, bool wakeLane_)
130{ 128{
131 lane_->cancel_request = CancelRequest::Hard; // it's now signaled to stop 129 lane_->cancel_request = CancelRequest::Hard; // it's now signaled to stop
132 //lane_->m_thread.get_stop_source().request_stop(); 130 // lane_->m_thread.get_stop_source().request_stop();
133 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired 131 if (wakeLane_) // wake the thread so that execution returns from any pending linda operation if desired
134 { 132 {
135 std::condition_variable* waiting_on = lane_->m_waiting_on; 133 std::condition_variable* waiting_on = lane_->m_waiting_on;
136 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr) 134 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr) {
137 {
138 waiting_on->notify_all(); 135 waiting_on->notify_all();
139 } 136 }
140 } 137 }
@@ -145,58 +142,43 @@ LUAG_FUNC(cancel_test)
145 142
146// ################################################################################################# 143// #################################################################################################
147 144
148CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hook_count_, lua_Duration duration_, bool wake_lane_) 145CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hookCount_, lua_Duration duration_, bool wakeLane_)
149{ 146{
150 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here 147 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
151 // We can read 'lane_->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) 148 // We can read 'lane_->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
152 if (lane_->m_status >= Lane::Done) 149 if (lane_->m_status >= Lane::Done) {
153 {
154 // say "ok" by default, including when lane is already done 150 // say "ok" by default, including when lane is already done
155 return CancelResult::Cancelled; 151 return CancelResult::Cancelled;
156 } 152 }
157 153
158 // signal the linda the wake up the thread so that it can react to the cancel query 154 // signal the linda the wake up the thread so that it can react to the cancel query
159 // let us hope we never land here with a pointer on a linda that has been destroyed... 155 // let us hope we never land here with a pointer on a linda that has been destroyed...
160 if (op_ == CancelOp::Soft) 156 if (op_ == CancelOp::Soft) {
161 { 157 return thread_cancel_soft(lane_, duration_, wakeLane_);
162 return thread_cancel_soft(lane_, duration_, wake_lane_); 158 } else if (static_cast<int>(op_) > static_cast<int>(CancelOp::Soft)) {
163 } 159 lua_sethook(lane_->L, cancel_hook, static_cast<int>(op_), hookCount_);
164 else if (static_cast<int>(op_) > static_cast<int>(CancelOp::Soft))
165 {
166 lua_sethook(lane_->L, cancel_hook, static_cast<int>(op_), hook_count_);
167 } 160 }
168 161
169 return thread_cancel_hard(lane_, duration_, wake_lane_); 162 return thread_cancel_hard(lane_, duration_, wakeLane_);
170} 163}
171 164
172// ################################################################################################# 165// #################################################################################################
173// ################################################################################################# 166// #################################################################################################
174 167
175CancelOp which_cancel_op(char const* op_string_) 168CancelOp which_cancel_op(char const* opString_)
176{ 169{
177 CancelOp op{ CancelOp::Invalid }; 170 CancelOp op{ CancelOp::Invalid };
178 if (strcmp(op_string_, "hard") == 0) 171 if (strcmp(opString_, "hard") == 0) {
179 {
180 op = CancelOp::Hard; 172 op = CancelOp::Hard;
181 } 173 } else if (strcmp(opString_, "soft") == 0) {
182 else if (strcmp(op_string_, "soft") == 0)
183 {
184 op = CancelOp::Soft; 174 op = CancelOp::Soft;
185 } 175 } else if (strcmp(opString_, "call") == 0) {
186 else if (strcmp(op_string_, "call") == 0)
187 {
188 op = CancelOp::MaskCall; 176 op = CancelOp::MaskCall;
189 } 177 } else if (strcmp(opString_, "ret") == 0) {
190 else if (strcmp(op_string_, "ret") == 0)
191 {
192 op = CancelOp::MaskRet; 178 op = CancelOp::MaskRet;
193 } 179 } else if (strcmp(opString_, "line") == 0) {
194 else if (strcmp(op_string_, "line") == 0)
195 {
196 op = CancelOp::MaskLine; 180 op = CancelOp::MaskLine;
197 } 181 } else if (strcmp(opString_, "count") == 0) {
198 else if (strcmp(op_string_, "count") == 0)
199 {
200 op = CancelOp::MaskCount; 182 op = CancelOp::MaskCount;
201 } 183 }
202 return op; 184 return op;
@@ -206,13 +188,11 @@ CancelOp which_cancel_op(char const* op_string_)
206 188
207[[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_) 189[[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_)
208{ 190{
209 if (lua_type(L_, idx_) == LUA_TSTRING) 191 if (lua_type(L_, idx_) == LUA_TSTRING) {
210 {
211 char const* const str{ lua_tostring(L_, idx_) }; 192 char const* const str{ lua_tostring(L_, idx_) };
212 CancelOp op{ which_cancel_op(str) }; 193 CancelOp op{ which_cancel_op(str) };
213 lua_remove(L_, idx_); // argument is processed, remove it 194 lua_remove(L_, idx_); // argument is processed, remove it
214 if (op == CancelOp::Invalid) 195 if (op == CancelOp::Invalid) {
215 {
216 raise_luaL_error(L_, "invalid hook option %s", str); 196 raise_luaL_error(L_, "invalid hook option %s", str);
217 } 197 }
218 return op; 198 return op;