aboutsummaryrefslogtreecommitdiff
path: root/src/linda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/linda.cpp')
-rw-r--r--src/linda.cpp256
1 files changed, 128 insertions, 128 deletions
diff --git a/src/linda.cpp b/src/linda.cpp
index 67a97c2..f88158a 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -127,11 +127,11 @@ template <bool OPT>
127 127
128// ################################################################################################# 128// #################################################################################################
129 129
130static void check_key_types(lua_State* L, int start_, int end_) 130static void check_key_types(lua_State* L_, int start_, int end_)
131{ 131{
132 for (int i{ start_ }; i <= end_; ++i) 132 for (int i{ start_ }; i <= end_; ++i)
133 { 133 {
134 LuaType const t{ lua_type_as_enum(L, i) }; 134 LuaType const t{ lua_type_as_enum(L_, i) };
135 switch (t) 135 switch (t)
136 { 136 {
137 case LuaType::BOOLEAN: 137 case LuaType::BOOLEAN:
@@ -144,25 +144,25 @@ static void check_key_types(lua_State* L, int start_, int end_)
144 static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel }; 144 static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel };
145 for (UniqueKey const& key : kKeysToCheck) 145 for (UniqueKey const& key : kKeysToCheck)
146 { 146 {
147 if (key.equals(L, i)) 147 if (key.equals(L_, i))
148 { 148 {
149 raise_luaL_error(L, "argument #%d: can't use %s as a key", i, key.m_debugName); 149 raise_luaL_error(L_, "argument #%d: can't use %s as a key", i, key.m_debugName);
150 break; 150 break;
151 } 151 }
152 } 152 }
153 } 153 }
154 break; 154 break;
155 } 155 }
156 raise_luaL_error(L, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i); 156 raise_luaL_error(L_, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i);
157 } 157 }
158} 158}
159 159
160// ################################################################################################# 160// #################################################################################################
161 161
162// used to perform all linda operations that access keepers 162// used to perform all linda operations that access keepers
163int Linda::ProtectedCall(lua_State* L, lua_CFunction f_) 163int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_)
164{ 164{
165 Linda* const linda{ ToLinda<false>(L, 1) }; 165 Linda* const linda{ ToLinda<false>(L_, 1) };
166 166
167 // acquire the keeper 167 // acquire the keeper
168 Keeper* const K{ linda->acquireKeeper() }; 168 Keeper* const K{ linda->acquireKeeper() };
@@ -170,13 +170,13 @@ int Linda::ProtectedCall(lua_State* L, lua_CFunction f_)
170 if (KL == nullptr) 170 if (KL == nullptr)
171 return 0; 171 return 0;
172 // if we didn't do anything wrong, the keeper stack should be clean 172 // if we didn't do anything wrong, the keeper stack should be clean
173 LUA_ASSERT(L, lua_gettop(KL) == 0); 173 LUA_ASSERT(L_, lua_gettop(KL) == 0);
174 174
175 // push the function to be called and move it before the arguments 175 // push the function to be called and move it before the arguments
176 lua_pushcfunction(L, f_); 176 lua_pushcfunction(L_, f_);
177 lua_insert(L, 1); 177 lua_insert(L_, 1);
178 // do a protected call 178 // do a protected call
179 int const rc{ lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) }; 179 int const rc{ lua_pcall(L_, lua_gettop(L_) - 1, LUA_MULTRET, 0) };
180 // whatever happens, the keeper state stack must be empty when we are done 180 // whatever happens, the keeper state stack must be empty when we are done
181 lua_settop(KL, 0); 181 lua_settop(KL, 0);
182 182
@@ -186,10 +186,10 @@ int Linda::ProtectedCall(lua_State* L, lua_CFunction f_)
186 // if there was an error, forward it 186 // if there was an error, forward it
187 if (rc != LUA_OK) 187 if (rc != LUA_OK)
188 { 188 {
189 raise_lua_error(L); 189 raise_lua_error(L_);
190 } 190 }
191 // return whatever the actual operation provided 191 // return whatever the actual operation provided
192 return lua_gettop(L); 192 return lua_gettop(L_);
193} 193}
194 194
195// ################################################################################################# 195// #################################################################################################
@@ -205,27 +205,27 @@ int Linda::ProtectedCall(lua_State* L, lua_CFunction f_)
205*/ 205*/
206LUAG_FUNC(linda_send) 206LUAG_FUNC(linda_send)
207{ 207{
208 auto send = [](lua_State* L) 208 auto send = [](lua_State* L_)
209 { 209 {
210 Linda* const linda{ ToLinda<false>(L, 1) }; 210 Linda* const linda{ ToLinda<false>(L_, 1) };
211 std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 211 std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
212 int key_i{ 2 }; // index of first key, if timeout not there 212 int key_i{ 2 }; // index of first key, if timeout not there
213 213
214 if (lua_type(L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion 214 if (lua_type(L_, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion
215 { 215 {
216 lua_Duration const duration{ lua_tonumber(L, 2) }; 216 lua_Duration const duration{ lua_tonumber(L_, 2) };
217 if (duration.count() >= 0.0) 217 if (duration.count() >= 0.0)
218 { 218 {
219 until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); 219 until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
220 } 220 }
221 ++key_i; 221 ++key_i;
222 } 222 }
223 else if (lua_isnil(L, 2)) // alternate explicit "infinite timeout" by passing nil before the key 223 else if (lua_isnil(L_, 2)) // alternate explicit "infinite timeout" by passing nil before the key
224 { 224 {
225 ++key_i; 225 ++key_i;
226 } 226 }
227 227
228 bool const as_nil_sentinel{ kNilSentinel.equals(L, key_i) }; // if not nullptr, send() will silently send a single nil if nothing is provided 228 bool const as_nil_sentinel{ kNilSentinel.equals(L_, key_i) }; // if not nullptr, send() will silently send a single nil if nothing is provided
229 if (as_nil_sentinel) 229 if (as_nil_sentinel)
230 { 230 {
231 // the real key to send data to is after the kNilSentinel marker 231 // the real key to send data to is after the kNilSentinel marker
@@ -233,31 +233,31 @@ LUAG_FUNC(linda_send)
233 } 233 }
234 234
235 // make sure the key is of a valid type 235 // make sure the key is of a valid type
236 check_key_types(L, key_i, key_i); 236 check_key_types(L_, key_i, key_i);
237 237
238 STACK_GROW(L, 1); 238 STACK_GROW(L_, 1);
239 239
240 // make sure there is something to send 240 // make sure there is something to send
241 if (lua_gettop(L) == key_i) 241 if (lua_gettop(L_) == key_i)
242 { 242 {
243 if (as_nil_sentinel) 243 if (as_nil_sentinel)
244 { 244 {
245 // send a single nil if nothing is provided 245 // send a single nil if nothing is provided
246 kNilSentinel.pushKey(L); 246 kNilSentinel.pushKey(L_);
247 } 247 }
248 else 248 else
249 { 249 {
250 raise_luaL_error(L, "no data to send"); 250 raise_luaL_error(L_, "no data to send");
251 } 251 }
252 } 252 }
253 253
254 // convert nils to some special non-nil sentinel in sent values 254 // convert nils to some special non-nil sentinel in sent values
255 keeper_toggle_nil_sentinels(L, key_i + 1, LookupMode::ToKeeper); 255 keeper_toggle_nil_sentinels(L_, key_i + 1, LookupMode::ToKeeper);
256 bool ret{ false }; 256 bool ret{ false };
257 CancelRequest cancel{ CancelRequest::None }; 257 CancelRequest cancel{ CancelRequest::None };
258 KeeperCallResult pushed; 258 KeeperCallResult pushed;
259 { 259 {
260 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L) }; 260 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) };
261 Keeper* const K{ linda->whichKeeper() }; 261 Keeper* const K{ linda->whichKeeper() };
262 KeeperState const KL{ K ? K->L : nullptr }; 262 KeeperState const KL{ K ? K->L : nullptr };
263 if (KL == nullptr) 263 if (KL == nullptr)
@@ -279,15 +279,15 @@ LUAG_FUNC(linda_send)
279 } 279 }
280 280
281 STACK_CHECK(KL, 0); 281 STACK_CHECK(KL, 0);
282 pushed = keeper_call(linda->U, KL, KEEPER_API(send), L, linda, key_i); 282 pushed = keeper_call(linda->U, KL, KEEPER_API(send), L_, linda, key_i);
283 if (!pushed.has_value()) 283 if (!pushed.has_value())
284 { 284 {
285 break; 285 break;
286 } 286 }
287 LUA_ASSERT(L, pushed.value() == 1); 287 LUA_ASSERT(L_, pushed.value() == 1);
288 288
289 ret = lua_toboolean(L, -1) ? true : false; 289 ret = lua_toboolean(L_, -1) ? true : false;
290 lua_pop(L, 1); 290 lua_pop(L_, 1);
291 291
292 if (ret) 292 if (ret)
293 { 293 {
@@ -309,9 +309,9 @@ LUAG_FUNC(linda_send)
309 { 309 {
310 // change status of lane to "waiting" 310 // change status of lane to "waiting"
311 prev_status = lane->m_status; // Running, most likely 311 prev_status = lane->m_status; // Running, most likely
312 LUA_ASSERT(L, prev_status == Lane::Running); // but check, just in case 312 LUA_ASSERT(L_, prev_status == Lane::Running); // but check, just in case
313 lane->m_status = Lane::Waiting; 313 lane->m_status = Lane::Waiting;
314 LUA_ASSERT(L, lane->m_waiting_on == nullptr); 314 LUA_ASSERT(L_, lane->m_waiting_on == nullptr);
315 lane->m_waiting_on = &linda->m_read_happened; 315 lane->m_waiting_on = &linda->m_read_happened;
316 } 316 }
317 // could not send because no room: wait until some data was read before trying again, or until timeout is reached 317 // could not send because no room: wait until some data was read before trying again, or until timeout is reached
@@ -331,26 +331,26 @@ LUAG_FUNC(linda_send)
331 331
332 if (!pushed.has_value()) 332 if (!pushed.has_value())
333 { 333 {
334 raise_luaL_error(L, "tried to copy unsupported types"); 334 raise_luaL_error(L_, "tried to copy unsupported types");
335 } 335 }
336 336
337 switch (cancel) 337 switch (cancel)
338 { 338 {
339 case CancelRequest::Soft: 339 case CancelRequest::Soft:
340 // if user wants to soft-cancel, the call returns lanes.cancel_error 340 // if user wants to soft-cancel, the call returns lanes.cancel_error
341 kCancelError.pushKey(L); 341 kCancelError.pushKey(L_);
342 return 1; 342 return 1;
343 343
344 case CancelRequest::Hard: 344 case CancelRequest::Hard:
345 // raise an error interrupting execution only in case of hard cancel 345 // raise an error interrupting execution only in case of hard cancel
346 raise_cancel_error(L); // raises an error and doesn't return 346 raise_cancel_error(L_); // raises an error and doesn't return
347 347
348 default: 348 default:
349 lua_pushboolean(L, ret); // true (success) or false (timeout) 349 lua_pushboolean(L_, ret); // true (success) or false (timeout)
350 return 1; 350 return 1;
351 } 351 }
352 }; 352 };
353 return Linda::ProtectedCall(L, send); 353 return Linda::ProtectedCall(L_, send);
354} 354}
355 355
356// ################################################################################################# 356// #################################################################################################
@@ -368,22 +368,22 @@ LUAG_FUNC(linda_send)
368 */ 368 */
369LUAG_FUNC(linda_receive) 369LUAG_FUNC(linda_receive)
370{ 370{
371 auto receive = [](lua_State* L) 371 auto receive = [](lua_State* L_)
372 { 372 {
373 Linda* const linda{ ToLinda<false>(L, 1) }; 373 Linda* const linda{ ToLinda<false>(L_, 1) };
374 std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 374 std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
375 int key_i{ 2 }; // index of first key, if timeout not there 375 int key_i{ 2 }; // index of first key, if timeout not there
376 376
377 if (lua_type(L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion 377 if (lua_type(L_, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion
378 { 378 {
379 lua_Duration const duration{ lua_tonumber(L, 2) }; 379 lua_Duration const duration{ lua_tonumber(L_, 2) };
380 if (duration.count() >= 0.0) 380 if (duration.count() >= 0.0)
381 { 381 {
382 until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); 382 until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
383 } 383 }
384 ++key_i; 384 ++key_i;
385 } 385 }
386 else if (lua_isnil(L, 2)) // alternate explicit "infinite timeout" by passing nil before the key 386 else if (lua_isnil(L_, 2)) // alternate explicit "infinite timeout" by passing nil before the key
387 { 387 {
388 ++key_i; 388 ++key_i;
389 } 389 }
@@ -391,39 +391,39 @@ LUAG_FUNC(linda_receive)
391 keeper_api_t selected_keeper_receive{ nullptr }; 391 keeper_api_t selected_keeper_receive{ nullptr };
392 int expected_pushed_min{ 0 }, expected_pushed_max{ 0 }; 392 int expected_pushed_min{ 0 }, expected_pushed_max{ 0 };
393 // are we in batched mode? 393 // are we in batched mode?
394 kLindaBatched.pushKey(L); 394 kLindaBatched.pushKey(L_);
395 int const is_batched{ lua501_equal(L, key_i, -1) }; 395 int const is_batched{ lua501_equal(L_, key_i, -1) };
396 lua_pop(L, 1); 396 lua_pop(L_, 1);
397 if (is_batched) 397 if (is_batched)
398 { 398 {
399 // no need to pass linda.batched in the keeper state 399 // no need to pass linda.batched in the keeper state
400 ++key_i; 400 ++key_i;
401 // make sure the keys are of a valid type 401 // make sure the keys are of a valid type
402 check_key_types(L, key_i, key_i); 402 check_key_types(L_, key_i, key_i);
403 // receive multiple values from a single slot 403 // receive multiple values from a single slot
404 selected_keeper_receive = KEEPER_API(receive_batched); 404 selected_keeper_receive = KEEPER_API(receive_batched);
405 // we expect a user-defined amount of return value 405 // we expect a user-defined amount of return value
406 expected_pushed_min = (int) luaL_checkinteger(L, key_i + 1); 406 expected_pushed_min = (int) luaL_checkinteger(L_, key_i + 1);
407 expected_pushed_max = (int) luaL_optinteger(L, key_i + 2, expected_pushed_min); 407 expected_pushed_max = (int) luaL_optinteger(L_, key_i + 2, expected_pushed_min);
408 // don't forget to count the key in addition to the values 408 // don't forget to count the key in addition to the values
409 ++expected_pushed_min; 409 ++expected_pushed_min;
410 ++expected_pushed_max; 410 ++expected_pushed_max;
411 if (expected_pushed_min > expected_pushed_max) 411 if (expected_pushed_min > expected_pushed_max)
412 { 412 {
413 raise_luaL_error(L, "batched min/max error"); 413 raise_luaL_error(L_, "batched min/max error");
414 } 414 }
415 } 415 }
416 else 416 else
417 { 417 {
418 // make sure the keys are of a valid type 418 // make sure the keys are of a valid type
419 check_key_types(L, key_i, lua_gettop(L)); 419 check_key_types(L_, key_i, lua_gettop(L_));
420 // receive a single value, checking multiple slots 420 // receive a single value, checking multiple slots
421 selected_keeper_receive = KEEPER_API(receive); 421 selected_keeper_receive = KEEPER_API(receive);
422 // we expect a single (value, key) pair of returned values 422 // we expect a single (value, key) pair of returned values
423 expected_pushed_min = expected_pushed_max = 2; 423 expected_pushed_min = expected_pushed_max = 2;
424 } 424 }
425 425
426 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L) }; 426 Lane* const lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) };
427 Keeper* const K{ linda->whichKeeper() }; 427 Keeper* const K{ linda->whichKeeper() };
428 KeeperState const KL{ K ? K->L : nullptr }; 428 KeeperState const KL{ K ? K->L : nullptr };
429 if (KL == nullptr) 429 if (KL == nullptr)
@@ -447,16 +447,16 @@ LUAG_FUNC(linda_receive)
447 } 447 }
448 448
449 // all arguments of receive() but the first are passed to the keeper's receive function 449 // all arguments of receive() but the first are passed to the keeper's receive function
450 pushed = keeper_call(linda->U, KL, selected_keeper_receive, L, linda, key_i); 450 pushed = keeper_call(linda->U, KL, selected_keeper_receive, L_, linda, key_i);
451 if (!pushed.has_value()) 451 if (!pushed.has_value())
452 { 452 {
453 break; 453 break;
454 } 454 }
455 if (pushed.value() > 0) 455 if (pushed.value() > 0)
456 { 456 {
457 LUA_ASSERT(L, pushed.value() >= expected_pushed_min && pushed.value() <= expected_pushed_max); 457 LUA_ASSERT(L_, pushed.value() >= expected_pushed_min && pushed.value() <= expected_pushed_max);
458 // replace sentinels with real nils 458 // replace sentinels with real nils
459 keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed.value(), LookupMode::FromKeeper); 459 keeper_toggle_nil_sentinels(L_, lua_gettop(L_) - pushed.value(), LookupMode::FromKeeper);
460 // To be done from within the 'K' locking area 460 // To be done from within the 'K' locking area
461 // 461 //
462 linda->m_read_happened.notify_all(); 462 linda->m_read_happened.notify_all();
@@ -475,9 +475,9 @@ LUAG_FUNC(linda_receive)
475 { 475 {
476 // change status of lane to "waiting" 476 // change status of lane to "waiting"
477 prev_status = lane->m_status; // Running, most likely 477 prev_status = lane->m_status; // Running, most likely
478 LUA_ASSERT(L, prev_status == Lane::Running); // but check, just in case 478 LUA_ASSERT(L_, prev_status == Lane::Running); // but check, just in case
479 lane->m_status = Lane::Waiting; 479 lane->m_status = Lane::Waiting;
480 LUA_ASSERT(L, lane->m_waiting_on == nullptr); 480 LUA_ASSERT(L_, lane->m_waiting_on == nullptr);
481 lane->m_waiting_on = &linda->m_write_happened; 481 lane->m_waiting_on = &linda->m_write_happened;
482 } 482 }
483 // not enough data to read: wakeup when data was sent, or when timeout is reached 483 // not enough data to read: wakeup when data was sent, or when timeout is reached
@@ -496,25 +496,25 @@ LUAG_FUNC(linda_receive)
496 496
497 if (!pushed.has_value()) 497 if (!pushed.has_value())
498 { 498 {
499 raise_luaL_error(L, "tried to copy unsupported types"); 499 raise_luaL_error(L_, "tried to copy unsupported types");
500 } 500 }
501 501
502 switch (cancel) 502 switch (cancel)
503 { 503 {
504 case CancelRequest::Soft: 504 case CancelRequest::Soft:
505 // if user wants to soft-cancel, the call returns kCancelError 505 // if user wants to soft-cancel, the call returns kCancelError
506 kCancelError.pushKey(L); 506 kCancelError.pushKey(L_);
507 return 1; 507 return 1;
508 508
509 case CancelRequest::Hard: 509 case CancelRequest::Hard:
510 // raise an error interrupting execution only in case of hard cancel 510 // raise an error interrupting execution only in case of hard cancel
511 raise_cancel_error(L); // raises an error and doesn't return 511 raise_cancel_error(L_); // raises an error and doesn't return
512 512
513 default: 513 default:
514 return pushed.value(); 514 return pushed.value();
515 } 515 }
516 }; 516 };
517 return Linda::ProtectedCall(L, receive); 517 return Linda::ProtectedCall(L_, receive);
518} 518}
519 519
520// ################################################################################################# 520// #################################################################################################
@@ -529,12 +529,12 @@ LUAG_FUNC(linda_receive)
529*/ 529*/
530LUAG_FUNC(linda_set) 530LUAG_FUNC(linda_set)
531{ 531{
532 auto set = [](lua_State* L) 532 auto set = [](lua_State* L_)
533 { 533 {
534 Linda* const linda{ ToLinda<false>(L, 1) }; 534 Linda* const linda{ ToLinda<false>(L_, 1) };
535 bool const has_value{ lua_gettop(L) > 2 }; 535 bool const has_value{ lua_gettop(L_) > 2 };
536 // make sure the key is of a valid type (throws an error if not the case) 536 // make sure the key is of a valid type (throws an error if not the case)
537 check_key_types(L, 2, 2); 537 check_key_types(L_, 2, 2);
538 538
539 Keeper* const K{ linda->whichKeeper() }; 539 Keeper* const K{ linda->whichKeeper() };
540 KeeperCallResult pushed; 540 KeeperCallResult pushed;
@@ -543,12 +543,12 @@ LUAG_FUNC(linda_set)
543 if (has_value) 543 if (has_value)
544 { 544 {
545 // convert nils to some special non-nil sentinel in sent values 545 // convert nils to some special non-nil sentinel in sent values
546 keeper_toggle_nil_sentinels(L, 3, LookupMode::ToKeeper); 546 keeper_toggle_nil_sentinels(L_, 3, LookupMode::ToKeeper);
547 } 547 }
548 pushed = keeper_call(linda->U, K->L, KEEPER_API(set), L, linda, 2); 548 pushed = keeper_call(linda->U, K->L, KEEPER_API(set), L_, linda, 2);
549 if (pushed.has_value()) // no error? 549 if (pushed.has_value()) // no error?
550 { 550 {
551 LUA_ASSERT(L, pushed.value() == 0 || pushed.value() == 1); 551 LUA_ASSERT(L_, pushed.value() == 0 || pushed.value() == 1);
552 552
553 if (has_value) 553 if (has_value)
554 { 554 {
@@ -558,7 +558,7 @@ LUAG_FUNC(linda_set)
558 if (pushed.value() == 1) 558 if (pushed.value() == 1)
559 { 559 {
560 // the key was full, but it is no longer the case, tell writers they should wake 560 // the key was full, but it is no longer the case, tell writers they should wake
561 LUA_ASSERT(L, lua_type(L, -1) == LUA_TBOOLEAN && lua_toboolean(L, -1) == 1); 561 LUA_ASSERT(L_, lua_type(L_, -1) == LUA_TBOOLEAN && lua_toboolean(L_, -1) == 1);
562 linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area 562 linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area
563 } 563 }
564 } 564 }
@@ -566,14 +566,14 @@ LUAG_FUNC(linda_set)
566 else // linda is cancelled 566 else // linda is cancelled
567 { 567 {
568 // do nothing and return lanes.cancel_error 568 // do nothing and return lanes.cancel_error
569 kCancelError.pushKey(L); 569 kCancelError.pushKey(L_);
570 pushed.emplace(1); 570 pushed.emplace(1);
571 } 571 }
572 572
573 // must trigger any error after keeper state has been released 573 // must trigger any error after keeper state has been released
574 return OptionalValue(pushed, L, "tried to copy unsupported types"); 574 return OptionalValue(pushed, L_, "tried to copy unsupported types");
575 }; 575 };
576 return Linda::ProtectedCall(L, set); 576 return Linda::ProtectedCall(L_, set);
577} 577}
578 578
579// ################################################################################################# 579// #################################################################################################
@@ -585,17 +585,17 @@ LUAG_FUNC(linda_set)
585 */ 585 */
586LUAG_FUNC(linda_count) 586LUAG_FUNC(linda_count)
587{ 587{
588 auto count = [](lua_State* L) 588 auto count = [](lua_State* L_)
589 { 589 {
590 Linda* const linda{ ToLinda<false>(L, 1) }; 590 Linda* const linda{ ToLinda<false>(L_, 1) };
591 // make sure the keys are of a valid type 591 // make sure the keys are of a valid type
592 check_key_types(L, 2, lua_gettop(L)); 592 check_key_types(L_, 2, lua_gettop(L_));
593 593
594 Keeper* const K{ linda->whichKeeper() }; 594 Keeper* const K{ linda->whichKeeper() };
595 KeeperCallResult const pushed{ keeper_call(linda->U, K->L, KEEPER_API(count), L, linda, 2) }; 595 KeeperCallResult const pushed{ keeper_call(linda->U, K->L, KEEPER_API(count), L_, linda, 2) };
596 return OptionalValue(pushed, L, "tried to count an invalid key"); 596 return OptionalValue(pushed, L_, "tried to count an invalid key");
597 }; 597 };
598 return Linda::ProtectedCall(L, count); 598 return Linda::ProtectedCall(L_, count);
599} 599}
600 600
601// ################################################################################################# 601// #################################################################################################
@@ -607,35 +607,35 @@ LUAG_FUNC(linda_count)
607*/ 607*/
608LUAG_FUNC(linda_get) 608LUAG_FUNC(linda_get)
609{ 609{
610 auto get = [](lua_State* L) 610 auto get = [](lua_State* L_)
611 { 611 {
612 Linda* const linda{ ToLinda<false>(L, 1) }; 612 Linda* const linda{ ToLinda<false>(L_, 1) };
613 lua_Integer const count{ luaL_optinteger(L, 3, 1) }; 613 lua_Integer const count{ luaL_optinteger(L_, 3, 1) };
614 luaL_argcheck(L, count >= 1, 3, "count should be >= 1"); 614 luaL_argcheck(L_, count >= 1, 3, "count should be >= 1");
615 luaL_argcheck(L, lua_gettop(L) <= 3, 4, "too many arguments"); 615 luaL_argcheck(L_, lua_gettop(L_) <= 3, 4, "too many arguments");
616 // make sure the key is of a valid type (throws an error if not the case) 616 // make sure the key is of a valid type (throws an error if not the case)
617 check_key_types(L, 2, 2); 617 check_key_types(L_, 2, 2);
618 618
619 KeeperCallResult pushed; 619 KeeperCallResult pushed;
620 if (linda->simulate_cancel == CancelRequest::None) 620 if (linda->simulate_cancel == CancelRequest::None)
621 { 621 {
622 Keeper* const K{ linda->whichKeeper() }; 622 Keeper* const K{ linda->whichKeeper() };
623 pushed = keeper_call(linda->U, K->L, KEEPER_API(get), L, linda, 2); 623 pushed = keeper_call(linda->U, K->L, KEEPER_API(get), L_, linda, 2);
624 if (pushed.value_or(0) > 0) 624 if (pushed.value_or(0) > 0)
625 { 625 {
626 keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed.value(), LookupMode::FromKeeper); 626 keeper_toggle_nil_sentinels(L_, lua_gettop(L_) - pushed.value(), LookupMode::FromKeeper);
627 } 627 }
628 } 628 }
629 else // linda is cancelled 629 else // linda is cancelled
630 { 630 {
631 // do nothing and return lanes.cancel_error 631 // do nothing and return lanes.cancel_error
632 kCancelError.pushKey(L); 632 kCancelError.pushKey(L_);
633 pushed.emplace(1); 633 pushed.emplace(1);
634 } 634 }
635 // an error can be raised if we attempt to read an unregistered function 635 // an error can be raised if we attempt to read an unregistered function
636 return OptionalValue(pushed, L, "tried to copy unsupported types"); 636 return OptionalValue(pushed, L_, "tried to copy unsupported types");
637 }; 637 };
638 return Linda::ProtectedCall(L, get); 638 return Linda::ProtectedCall(L_, get);
639} 639}
640 640
641// ################################################################################################# 641// #################################################################################################
@@ -648,38 +648,38 @@ LUAG_FUNC(linda_get)
648*/ 648*/
649LUAG_FUNC(linda_limit) 649LUAG_FUNC(linda_limit)
650{ 650{
651 auto limit = [](lua_State* L) 651 auto limit = [](lua_State* L_)
652 { 652 {
653 Linda* const linda{ ToLinda<false>(L, 1) }; 653 Linda* const linda{ ToLinda<false>(L_, 1) };
654 // make sure we got 3 arguments: the linda, a key and a limit 654 // make sure we got 3 arguments: the linda, a key and a limit
655 luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments"); 655 luaL_argcheck( L_, lua_gettop( L_) == 3, 2, "wrong number of arguments");
656 // make sure we got a numeric limit 656 // make sure we got a numeric limit
657 luaL_checknumber( L, 3); 657 luaL_checknumber( L_, 3);
658 // make sure the key is of a valid type 658 // make sure the key is of a valid type
659 check_key_types( L, 2, 2); 659 check_key_types( L_, 2, 2);
660 660
661 KeeperCallResult pushed; 661 KeeperCallResult pushed;
662 if (linda->simulate_cancel == CancelRequest::None) 662 if (linda->simulate_cancel == CancelRequest::None)
663 { 663 {
664 Keeper* const K{ linda->whichKeeper() }; 664 Keeper* const K{ linda->whichKeeper() };
665 pushed = keeper_call(linda->U, K->L, KEEPER_API(limit), L, linda, 2); 665 pushed = keeper_call(linda->U, K->L, KEEPER_API(limit), L_, linda, 2);
666 LUA_ASSERT(L, pushed.has_value() && (pushed.value() == 0 || pushed.value() == 1)); // no error, optional boolean value saying if we should wake blocked writer threads 666 LUA_ASSERT(L_, pushed.has_value() && (pushed.value() == 0 || pushed.value() == 1)); // no error, optional boolean value saying if we should wake blocked writer threads
667 if (pushed.value() == 1) 667 if (pushed.value() == 1)
668 { 668 {
669 LUA_ASSERT(L, lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); 669 LUA_ASSERT(L_, lua_type( L_, -1) == LUA_TBOOLEAN && lua_toboolean( L_, -1) == 1);
670 linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area 670 linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area
671 } 671 }
672 } 672 }
673 else // linda is cancelled 673 else // linda is cancelled
674 { 674 {
675 // do nothing and return lanes.cancel_error 675 // do nothing and return lanes.cancel_error
676 kCancelError.pushKey(L); 676 kCancelError.pushKey(L_);
677 pushed.emplace(1); 677 pushed.emplace(1);
678 } 678 }
679 // propagate pushed boolean if any 679 // propagate pushed boolean if any
680 return pushed.value(); 680 return pushed.value();
681 }; 681 };
682 return Linda::ProtectedCall(L, limit); 682 return Linda::ProtectedCall(L_, limit);
683} 683}
684 684
685// ################################################################################################# 685// #################################################################################################
@@ -691,10 +691,10 @@ LUAG_FUNC(linda_limit)
691*/ 691*/
692LUAG_FUNC(linda_cancel) 692LUAG_FUNC(linda_cancel)
693{ 693{
694 Linda* const linda{ ToLinda<false>(L, 1) }; 694 Linda* const linda{ ToLinda<false>(L_, 1) };
695 char const* who = luaL_optstring(L, 2, "both"); 695 char const* who = luaL_optstring(L_, 2, "both");
696 // make sure we got 3 arguments: the linda, a key and a limit 696 // make sure we got 3 arguments: the linda, a key and a limit
697 luaL_argcheck(L, lua_gettop(L) <= 2, 2, "wrong number of arguments"); 697 luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments");
698 698
699 linda->simulate_cancel = CancelRequest::Soft; 699 linda->simulate_cancel = CancelRequest::Soft;
700 if (strcmp(who, "both") == 0) // tell everyone writers to wake up 700 if (strcmp(who, "both") == 0) // tell everyone writers to wake up
@@ -716,7 +716,7 @@ LUAG_FUNC(linda_cancel)
716 } 716 }
717 else 717 else
718 { 718 {
719 raise_luaL_error(L, "unknown wake hint '%s'", who); 719 raise_luaL_error(L_, "unknown wake hint '%s'", who);
720 } 720 }
721 return 0; 721 return 0;
722} 722}
@@ -735,8 +735,8 @@ LUAG_FUNC(linda_cancel)
735*/ 735*/
736LUAG_FUNC(linda_deep) 736LUAG_FUNC(linda_deep)
737{ 737{
738 Linda* const linda{ ToLinda<false>(L, 1) }; 738 Linda* const linda{ ToLinda<false>(L_, 1) };
739 lua_pushlightuserdata(L, linda); // just the address 739 lua_pushlightuserdata(L_, linda); // just the address
740 return 1; 740 return 1;
741} 741}
742 742
@@ -751,9 +751,9 @@ LUAG_FUNC(linda_deep)
751*/ 751*/
752 752
753template <bool OPT> 753template <bool OPT>
754[[nodiscard]] static int LindaToString(lua_State* L, int idx_) 754[[nodiscard]] static int LindaToString(lua_State* L_, int idx_)
755{ 755{
756 Linda* const linda{ ToLinda<OPT>(L, idx_) }; 756 Linda* const linda{ ToLinda<OPT>(L_, idx_) };
757 if (linda != nullptr) 757 if (linda != nullptr)
758 { 758 {
759 char text[128]; 759 char text[128];
@@ -762,7 +762,7 @@ template <bool OPT>
762 len = sprintf(text, "Linda: %.*s", (int) sizeof(text) - 8, linda->getName()); 762 len = sprintf(text, "Linda: %.*s", (int) sizeof(text) - 8, linda->getName());
763 else 763 else
764 len = sprintf(text, "Linda: %p", linda); 764 len = sprintf(text, "Linda: %p", linda);
765 lua_pushlstring(L, text, len); 765 lua_pushlstring(L_, text, len);
766 return 1; 766 return 1;
767 } 767 }
768 return 0; 768 return 0;
@@ -770,7 +770,7 @@ template <bool OPT>
770 770
771LUAG_FUNC(linda_tostring) 771LUAG_FUNC(linda_tostring)
772{ 772{
773 return LindaToString<false>(L, 1); 773 return LindaToString<false>(L_, 1);
774} 774}
775 775
776// ################################################################################################# 776// #################################################################################################
@@ -786,21 +786,21 @@ LUAG_FUNC(linda_concat)
786{ // linda1? linda2? 786{ // linda1? linda2?
787 bool atLeastOneLinda{ false }; 787 bool atLeastOneLinda{ false };
788 // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. 788 // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both.
789 if (LindaToString<true>(L, 1)) 789 if (LindaToString<true>(L_, 1))
790 { 790 {
791 atLeastOneLinda = true; 791 atLeastOneLinda = true;
792 lua_replace(L, 1); 792 lua_replace(L_, 1);
793 } 793 }
794 if (LindaToString<true>(L, 2)) 794 if (LindaToString<true>(L_, 2))
795 { 795 {
796 atLeastOneLinda = true; 796 atLeastOneLinda = true;
797 lua_replace(L, 2); 797 lua_replace(L_, 2);
798 } 798 }
799 if (!atLeastOneLinda) // should not be possible 799 if (!atLeastOneLinda) // should not be possible
800 { 800 {
801 raise_luaL_error(L, "internal error: linda_concat called on non-Linda"); 801 raise_luaL_error(L_, "internal error: linda_concat called on non-Linda");
802 } 802 }
803 lua_concat(L, 2); 803 lua_concat(L_, 2);
804 return 1; 804 return 1;
805} 805}
806 806
@@ -812,12 +812,12 @@ LUAG_FUNC(linda_concat)
812 */ 812 */
813LUAG_FUNC(linda_dump) 813LUAG_FUNC(linda_dump)
814{ 814{
815 auto dump = [](lua_State* L) 815 auto dump = [](lua_State* L_)
816 { 816 {
817 Linda* const linda{ ToLinda<false>(L, 1) }; 817 Linda* const linda{ ToLinda<false>(L_, 1) };
818 return keeper_push_linda_storage(*linda, DestState{ L }); 818 return keeper_push_linda_storage(*linda, DestState{ L_ });
819 }; 819 };
820 return Linda::ProtectedCall(L, dump); 820 return Linda::ProtectedCall(L_, dump);
821} 821}
822 822
823// ################################################################################################# 823// #################################################################################################
@@ -828,12 +828,12 @@ LUAG_FUNC(linda_dump)
828 */ 828 */
829LUAG_FUNC(linda_towatch) 829LUAG_FUNC(linda_towatch)
830{ 830{
831 Linda* const linda{ ToLinda<false>(L, 1) }; 831 Linda* const linda{ ToLinda<false>(L_, 1) };
832 int pushed{ keeper_push_linda_storage(*linda, DestState{ L }) }; 832 int pushed{ keeper_push_linda_storage(*linda, DestState{ L_ }) };
833 if (pushed == 0) 833 if (pushed == 0)
834 { 834 {
835 // if the linda is empty, don't return nil 835 // if the linda is empty, don't return nil
836 pushed = LindaToString<false>(L, 1); 836 pushed = LindaToString<false>(L_, 1);
837 } 837 }
838 return pushed; 838 return pushed;
839} 839}
@@ -870,17 +870,17 @@ namespace global {
870 */ 870 */
871LUAG_FUNC(linda) 871LUAG_FUNC(linda)
872{ 872{
873 int const top{ lua_gettop(L) }; 873 int const top{ lua_gettop(L_) };
874 luaL_argcheck(L, top <= 2, top, "too many arguments"); 874 luaL_argcheck(L_, top <= 2, top, "too many arguments");
875 if (top == 1) 875 if (top == 1)
876 { 876 {
877 LuaType const t{ lua_type_as_enum(L, 1) }; 877 LuaType const t{ lua_type_as_enum(L_, 1) };
878 luaL_argcheck(L, t == LuaType::STRING || t == LuaType::NUMBER, 1, "wrong parameter (should be a string or a number)"); 878 luaL_argcheck(L_, t == LuaType::STRING || t == LuaType::NUMBER, 1, "wrong parameter (should be a string or a number)");
879 } 879 }
880 else if (top == 2) 880 else if (top == 2)
881 { 881 {
882 luaL_checktype(L, 1, LUA_TSTRING); 882 luaL_checktype(L_, 1, LUA_TSTRING);
883 luaL_checktype(L, 2, LUA_TNUMBER); 883 luaL_checktype(L_, 2, LUA_TNUMBER);
884 } 884 }
885 return LindaFactory::Instance.pushDeepUserdata(DestState{ L }, 0); 885 return LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, 0);
886} 886}