diff options
Diffstat (limited to 'src/linda.cpp')
-rw-r--r-- | src/linda.cpp | 147 |
1 files changed, 80 insertions, 67 deletions
diff --git a/src/linda.cpp b/src/linda.cpp index e749f52..dbd6b21 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -39,8 +39,12 @@ THE SOFTWARE. | |||
39 | #include "universe.h" | 39 | #include "universe.h" |
40 | 40 | ||
41 | #include <array> | 41 | #include <array> |
42 | #include <functional> | ||
42 | #include <variant> | 43 | #include <variant> |
43 | 44 | ||
45 | // xxh64 of string "CANCEL_ERROR" generated at https://www.pelock.com/products/hash-calculator | ||
46 | static constexpr UniqueKey BATCH_SENTINEL{ 0x2DDFEE0968C62AA7ull, "linda.batched" }; | ||
47 | |||
44 | /* | 48 | /* |
45 | * Actual data is kept within a keeper state, which is hashed by the 'Linda' | 49 | * Actual data is kept within a keeper state, which is hashed by the 'Linda' |
46 | * pointer (which is same to all userdatas pointing to it). | 50 | * pointer (which is same to all userdatas pointing to it). |
@@ -140,14 +144,14 @@ class Linda : public DeepPrelude // Deep userdata MUST start with this header | |||
140 | [[nodiscard]] static void* linda_id(lua_State*, DeepOp); | 144 | [[nodiscard]] static void* linda_id(lua_State*, DeepOp); |
141 | 145 | ||
142 | template<bool OPT> | 146 | template<bool OPT> |
143 | [[nodiscard]] static inline Linda* lua_toLinda(lua_State* L, int idx_) | 147 | [[nodiscard]] static inline Linda* ToLinda(lua_State* L, int idx_) |
144 | { | 148 | { |
145 | Linda* const linda{ static_cast<Linda*>(luaG_todeep(L, linda_id, idx_)) }; | 149 | Linda* const linda{ static_cast<Linda*>(luaG_todeep(L, linda_id, idx_)) }; |
146 | if (!OPT) | 150 | if constexpr (!OPT) |
147 | { | 151 | { |
148 | luaL_argcheck(L, linda != nullptr, idx_, "expecting a linda object"); | 152 | luaL_argcheck(L, linda != nullptr, idx_, "expecting a linda object"); |
153 | ASSERT_L(linda->U == universe_get(L)); | ||
149 | } | 154 | } |
150 | ASSERT_L(linda->U == universe_get(L)); | ||
151 | return linda; | 155 | return linda; |
152 | } | 156 | } |
153 | 157 | ||
@@ -157,10 +161,28 @@ static void check_key_types(lua_State* L, int start_, int end_) | |||
157 | { | 161 | { |
158 | for (int i{ start_ }; i <= end_; ++i) | 162 | for (int i{ start_ }; i <= end_; ++i) |
159 | { | 163 | { |
160 | int const t{ lua_type(L, i) }; | 164 | LuaType const t{ lua_type_as_enum(L, i) }; |
161 | if (t == LUA_TBOOLEAN || t == LUA_TNUMBER || t == LUA_TSTRING || t == LUA_TLIGHTUSERDATA) | 165 | switch (t) |
162 | { | 166 | { |
167 | case LuaType::BOOLEAN: | ||
168 | case LuaType::NUMBER: | ||
169 | case LuaType::STRING: | ||
163 | continue; | 170 | continue; |
171 | |||
172 | case LuaType::LIGHTUSERDATA: | ||
173 | { | ||
174 | // NIL_SENTINEL isn't publicly exposed, but it doesn't hurt to check | ||
175 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> to_check{ BATCH_SENTINEL, CANCEL_ERROR, NIL_SENTINEL }; | ||
176 | for (UniqueKey const& key : to_check) | ||
177 | { | ||
178 | if (key.equals(L, i)) | ||
179 | { | ||
180 | luaL_error(L, "argument #%d: can't use %s as a key", i, key.m_debugName); // doesn't return | ||
181 | break; | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | break; | ||
164 | } | 186 | } |
165 | luaL_error(L, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i); // doesn't return | 187 | luaL_error(L, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i); // doesn't return |
166 | } | 188 | } |
@@ -170,7 +192,7 @@ static void check_key_types(lua_State* L, int start_, int end_) | |||
170 | 192 | ||
171 | LUAG_FUNC(linda_protected_call) | 193 | LUAG_FUNC(linda_protected_call) |
172 | { | 194 | { |
173 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 195 | Linda* const linda{ ToLinda<false>(L, 1) }; |
174 | 196 | ||
175 | // acquire the keeper | 197 | // acquire the keeper |
176 | Keeper* const K{ keeper_acquire(linda->U->keepers, linda->hashSeed()) }; | 198 | Keeper* const K{ keeper_acquire(linda->U->keepers, linda->hashSeed()) }; |
@@ -209,7 +231,7 @@ LUAG_FUNC(linda_protected_call) | |||
209 | */ | 231 | */ |
210 | LUAG_FUNC(linda_send) | 232 | LUAG_FUNC(linda_send) |
211 | { | 233 | { |
212 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 234 | Linda* const linda{ ToLinda<false>(L, 1) }; |
213 | std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 235 | std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
214 | int key_i{ 2 }; // index of first key, if timeout not there | 236 | int key_i{ 2 }; // index of first key, if timeout not there |
215 | 237 | ||
@@ -257,7 +279,7 @@ LUAG_FUNC(linda_send) | |||
257 | keeper_toggle_nil_sentinels(L, key_i + 1, LookupMode::ToKeeper); | 279 | keeper_toggle_nil_sentinels(L, key_i + 1, LookupMode::ToKeeper); |
258 | bool ret{ false }; | 280 | bool ret{ false }; |
259 | CancelRequest cancel{ CancelRequest::None }; | 281 | CancelRequest cancel{ CancelRequest::None }; |
260 | int pushed{ 0 }; | 282 | KeeperCallResult pushed; |
261 | { | 283 | { |
262 | Lane* const lane{ LANE_POINTER_REGKEY.readLightUserDataValue<Lane>(L) }; | 284 | Lane* const lane{ LANE_POINTER_REGKEY.readLightUserDataValue<Lane>(L) }; |
263 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 285 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
@@ -276,17 +298,17 @@ LUAG_FUNC(linda_send) | |||
276 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything | 298 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything |
277 | if (!try_again || cancel != CancelRequest::None) | 299 | if (!try_again || cancel != CancelRequest::None) |
278 | { | 300 | { |
279 | pushed = 0; | 301 | pushed.emplace(0); |
280 | break; | 302 | break; |
281 | } | 303 | } |
282 | 304 | ||
283 | STACK_CHECK(KL, 0); | 305 | STACK_CHECK(KL, 0); |
284 | pushed = keeper_call(linda->U, KL, KEEPER_API(send), L, linda, key_i); | 306 | pushed = keeper_call(linda->U, KL, KEEPER_API(send), L, linda, key_i); |
285 | if (pushed < 0) | 307 | if (!pushed.has_value()) |
286 | { | 308 | { |
287 | break; | 309 | break; |
288 | } | 310 | } |
289 | ASSERT_L(pushed == 1); | 311 | ASSERT_L(pushed.value() == 1); |
290 | 312 | ||
291 | ret = lua_toboolean(L, -1) ? true : false; | 313 | ret = lua_toboolean(L, -1) ? true : false; |
292 | lua_pop(L, 1); | 314 | lua_pop(L, 1); |
@@ -331,9 +353,9 @@ LUAG_FUNC(linda_send) | |||
331 | STACK_CHECK(KL, 0); | 353 | STACK_CHECK(KL, 0); |
332 | } | 354 | } |
333 | 355 | ||
334 | if (pushed < 0) | 356 | if (!pushed.has_value()) |
335 | { | 357 | { |
336 | return luaL_error(L, "tried to copy unsupported types"); | 358 | luaL_error(L, "tried to copy unsupported types"); // doesn't return |
337 | } | 359 | } |
338 | 360 | ||
339 | switch (cancel) | 361 | switch (cancel) |
@@ -366,11 +388,9 @@ LUAG_FUNC(linda_send) | |||
366 | * returns the actual consumed values, or nil if there weren't enough values to consume | 388 | * returns the actual consumed values, or nil if there weren't enough values to consume |
367 | * | 389 | * |
368 | */ | 390 | */ |
369 | // xxh64 of string "CANCEL_ERROR" generated at https://www.pelock.com/products/hash-calculator | ||
370 | static constexpr UniqueKey BATCH_SENTINEL{ 0x2DDFEE0968C62AA7ull }; | ||
371 | LUAG_FUNC(linda_receive) | 391 | LUAG_FUNC(linda_receive) |
372 | { | 392 | { |
373 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 393 | 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() }; | 394 | 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 | 395 | int key_i{ 2 }; // index of first key, if timeout not there |
376 | 396 | ||
@@ -430,7 +450,7 @@ LUAG_FUNC(linda_receive) | |||
430 | return 0; | 450 | return 0; |
431 | 451 | ||
432 | CancelRequest cancel{ CancelRequest::None }; | 452 | CancelRequest cancel{ CancelRequest::None }; |
433 | int pushed{ 0 }; | 453 | KeeperCallResult pushed; |
434 | STACK_CHECK_START_REL(KL, 0); | 454 | STACK_CHECK_START_REL(KL, 0); |
435 | for (bool try_again{ true };;) | 455 | for (bool try_again{ true };;) |
436 | { | 456 | { |
@@ -442,21 +462,21 @@ LUAG_FUNC(linda_receive) | |||
442 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything | 462 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything |
443 | if (!try_again || cancel != CancelRequest::None) | 463 | if (!try_again || cancel != CancelRequest::None) |
444 | { | 464 | { |
445 | pushed = 0; | 465 | pushed.emplace(0); |
446 | break; | 466 | break; |
447 | } | 467 | } |
448 | 468 | ||
449 | // all arguments of receive() but the first are passed to the keeper's receive function | 469 | // 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); | 470 | pushed = keeper_call(linda->U, KL, selected_keeper_receive, L, linda, key_i); |
451 | if (pushed < 0) | 471 | if (!pushed.has_value()) |
452 | { | 472 | { |
453 | break; | 473 | break; |
454 | } | 474 | } |
455 | if (pushed > 0) | 475 | if (pushed.value() > 0) |
456 | { | 476 | { |
457 | ASSERT_L(pushed >= expected_pushed_min && pushed <= expected_pushed_max); | 477 | ASSERT_L(pushed.value() >= expected_pushed_min && pushed.value() <= expected_pushed_max); |
458 | // replace sentinels with real nils | 478 | // replace sentinels with real nils |
459 | keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, LookupMode::FromKeeper); | 479 | keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed.value(), LookupMode::FromKeeper); |
460 | // To be done from within the 'K' locking area | 480 | // To be done from within the 'K' locking area |
461 | // | 481 | // |
462 | linda->m_read_happened.notify_all(); | 482 | linda->m_read_happened.notify_all(); |
@@ -494,7 +514,7 @@ LUAG_FUNC(linda_receive) | |||
494 | } | 514 | } |
495 | STACK_CHECK(KL, 0); | 515 | STACK_CHECK(KL, 0); |
496 | 516 | ||
497 | if (pushed < 0) | 517 | if (!pushed.has_value()) |
498 | { | 518 | { |
499 | return luaL_error(L, "tried to copy unsupported types"); | 519 | return luaL_error(L, "tried to copy unsupported types"); |
500 | } | 520 | } |
@@ -511,7 +531,7 @@ LUAG_FUNC(linda_receive) | |||
511 | raise_cancel_error(L); // raises an error and doesn't return | 531 | raise_cancel_error(L); // raises an error and doesn't return |
512 | 532 | ||
513 | default: | 533 | default: |
514 | return pushed; | 534 | return pushed.value(); |
515 | } | 535 | } |
516 | } | 536 | } |
517 | 537 | ||
@@ -527,13 +547,13 @@ LUAG_FUNC(linda_receive) | |||
527 | */ | 547 | */ |
528 | LUAG_FUNC(linda_set) | 548 | LUAG_FUNC(linda_set) |
529 | { | 549 | { |
530 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 550 | Linda* const linda{ ToLinda<false>(L, 1) }; |
531 | bool const has_value{ lua_gettop(L) > 2 }; | 551 | bool const has_value{ lua_gettop(L) > 2 }; |
532 | // make sure the key is of a valid type (throws an error if not the case) | 552 | // make sure the key is of a valid type (throws an error if not the case) |
533 | check_key_types(L, 2, 2); | 553 | check_key_types(L, 2, 2); |
534 | 554 | ||
535 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 555 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
536 | int pushed{ 0 }; | 556 | KeeperCallResult pushed; |
537 | if (linda->simulate_cancel == CancelRequest::None) | 557 | if (linda->simulate_cancel == CancelRequest::None) |
538 | { | 558 | { |
539 | if (has_value) | 559 | if (has_value) |
@@ -542,16 +562,16 @@ LUAG_FUNC(linda_set) | |||
542 | keeper_toggle_nil_sentinels(L, 3, LookupMode::ToKeeper); | 562 | keeper_toggle_nil_sentinels(L, 3, LookupMode::ToKeeper); |
543 | } | 563 | } |
544 | pushed = keeper_call(linda->U, K->L, KEEPER_API(set), L, linda, 2); | 564 | pushed = keeper_call(linda->U, K->L, KEEPER_API(set), L, linda, 2); |
545 | if (pushed >= 0) // no error? | 565 | if (pushed.has_value()) // no error? |
546 | { | 566 | { |
547 | ASSERT_L(pushed == 0 || pushed == 1); | 567 | ASSERT_L(pushed.value() == 0 || pushed.value() == 1); |
548 | 568 | ||
549 | if (has_value) | 569 | if (has_value) |
550 | { | 570 | { |
551 | // we put some data in the slot, tell readers that they should wake | 571 | // we put some data in the slot, tell readers that they should wake |
552 | linda->m_write_happened.notify_all(); // To be done from within the 'K' locking area | 572 | linda->m_write_happened.notify_all(); // To be done from within the 'K' locking area |
553 | } | 573 | } |
554 | if (pushed == 1) | 574 | if (pushed.value() == 1) |
555 | { | 575 | { |
556 | // the key was full, but it is no longer the case, tell writers they should wake | 576 | // the key was full, but it is no longer the case, tell writers they should wake |
557 | ASSERT_L(lua_type(L, -1) == LUA_TBOOLEAN && lua_toboolean(L, -1) == 1); | 577 | ASSERT_L(lua_type(L, -1) == LUA_TBOOLEAN && lua_toboolean(L, -1) == 1); |
@@ -563,11 +583,11 @@ LUAG_FUNC(linda_set) | |||
563 | { | 583 | { |
564 | // do nothing and return lanes.cancel_error | 584 | // do nothing and return lanes.cancel_error |
565 | CANCEL_ERROR.pushKey(L); | 585 | CANCEL_ERROR.pushKey(L); |
566 | pushed = 1; | 586 | pushed.emplace(1); |
567 | } | 587 | } |
568 | 588 | ||
569 | // must trigger any error after keeper state has been released | 589 | // must trigger any error after keeper state has been released |
570 | return (pushed < 0) ? luaL_error(L, "tried to copy unsupported types") : pushed; | 590 | return OptionalValue(pushed, L, "tried to copy unsupported types"); |
571 | } | 591 | } |
572 | 592 | ||
573 | // ################################################################################################# | 593 | // ################################################################################################# |
@@ -579,17 +599,13 @@ LUAG_FUNC(linda_set) | |||
579 | */ | 599 | */ |
580 | LUAG_FUNC(linda_count) | 600 | LUAG_FUNC(linda_count) |
581 | { | 601 | { |
582 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 602 | Linda* const linda{ ToLinda<false>(L, 1) }; |
583 | // make sure the keys are of a valid type | 603 | // make sure the keys are of a valid type |
584 | check_key_types(L, 2, lua_gettop(L)); | 604 | check_key_types(L, 2, lua_gettop(L)); |
585 | 605 | ||
586 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 606 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
587 | int const pushed{ keeper_call(linda->U, K->L, KEEPER_API(count), L, linda, 2) }; | 607 | KeeperCallResult const pushed{ keeper_call(linda->U, K->L, KEEPER_API(count), L, linda, 2) }; |
588 | if (pushed < 0) | 608 | return OptionalValue(pushed, L, "tried to count an invalid key"); |
589 | { | ||
590 | return luaL_error(L, "tried to count an invalid key"); | ||
591 | } | ||
592 | return pushed; | ||
593 | } | 609 | } |
594 | 610 | ||
595 | // ################################################################################################# | 611 | // ################################################################################################# |
@@ -601,36 +617,31 @@ LUAG_FUNC(linda_count) | |||
601 | */ | 617 | */ |
602 | LUAG_FUNC(linda_get) | 618 | LUAG_FUNC(linda_get) |
603 | { | 619 | { |
604 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 620 | Linda* const linda{ ToLinda<false>(L, 1) }; |
605 | lua_Integer const count{ luaL_optinteger(L, 3, 1) }; | 621 | lua_Integer const count{ luaL_optinteger(L, 3, 1) }; |
606 | luaL_argcheck(L, count >= 1, 3, "count should be >= 1"); | 622 | luaL_argcheck(L, count >= 1, 3, "count should be >= 1"); |
607 | luaL_argcheck(L, lua_gettop(L) <= 3, 4, "too many arguments"); | 623 | luaL_argcheck(L, lua_gettop(L) <= 3, 4, "too many arguments"); |
608 | // make sure the key is of a valid type (throws an error if not the case) | 624 | // make sure the key is of a valid type (throws an error if not the case) |
609 | check_key_types(L, 2, 2); | 625 | check_key_types(L, 2, 2); |
610 | 626 | ||
611 | int pushed{ 0 }; | 627 | KeeperCallResult pushed; |
612 | if (linda->simulate_cancel == CancelRequest::None) | 628 | if (linda->simulate_cancel == CancelRequest::None) |
613 | { | 629 | { |
614 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 630 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
615 | pushed = keeper_call(linda->U, K->L, KEEPER_API(get), L, linda, 2); | 631 | pushed = keeper_call(linda->U, K->L, KEEPER_API(get), L, linda, 2); |
616 | if (pushed > 0) | 632 | if (pushed.value_or(0) > 0) |
617 | { | 633 | { |
618 | keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, LookupMode::FromKeeper); | 634 | keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed.value(), LookupMode::FromKeeper); |
619 | } | 635 | } |
620 | } | 636 | } |
621 | else // linda is cancelled | 637 | else // linda is cancelled |
622 | { | 638 | { |
623 | // do nothing and return lanes.cancel_error | 639 | // do nothing and return lanes.cancel_error |
624 | CANCEL_ERROR.pushKey(L); | 640 | CANCEL_ERROR.pushKey(L); |
625 | pushed = 1; | 641 | pushed.emplace(1); |
626 | } | 642 | } |
627 | // an error can be raised if we attempt to read an unregistered function | 643 | // an error can be raised if we attempt to read an unregistered function |
628 | if (pushed < 0) | 644 | return OptionalValue(pushed, L, "tried to copy unsupported types"); |
629 | { | ||
630 | return luaL_error(L, "tried to copy unsupported types"); | ||
631 | } | ||
632 | |||
633 | return pushed; | ||
634 | } | 645 | } |
635 | 646 | ||
636 | // ################################################################################################# | 647 | // ################################################################################################# |
@@ -641,9 +652,9 @@ LUAG_FUNC(linda_get) | |||
641 | * Set limit to 1 Linda keys. | 652 | * Set limit to 1 Linda keys. |
642 | * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so | 653 | * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so |
643 | */ | 654 | */ |
644 | LUAG_FUNC( linda_limit) | 655 | LUAG_FUNC(linda_limit) |
645 | { | 656 | { |
646 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 657 | Linda* const linda{ ToLinda<false>(L, 1) }; |
647 | // make sure we got 3 arguments: the linda, a key and a limit | 658 | // make sure we got 3 arguments: the linda, a key and a limit |
648 | luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments"); | 659 | luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments"); |
649 | // make sure we got a numeric limit | 660 | // make sure we got a numeric limit |
@@ -651,13 +662,13 @@ LUAG_FUNC( linda_limit) | |||
651 | // make sure the key is of a valid type | 662 | // make sure the key is of a valid type |
652 | check_key_types( L, 2, 2); | 663 | check_key_types( L, 2, 2); |
653 | 664 | ||
654 | int pushed{ 0 }; | 665 | KeeperCallResult pushed; |
655 | if (linda->simulate_cancel == CancelRequest::None) | 666 | if (linda->simulate_cancel == CancelRequest::None) |
656 | { | 667 | { |
657 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 668 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
658 | pushed = keeper_call(linda->U, K->L, KEEPER_API(limit), L, linda, 2); | 669 | pushed = keeper_call(linda->U, K->L, KEEPER_API(limit), L, linda, 2); |
659 | ASSERT_L( pushed == 0 || pushed == 1); // no error, optional boolean value saying if we should wake blocked writer threads | 670 | ASSERT_L( pushed.has_value() && (pushed.value() == 0 || pushed.value() == 1)); // no error, optional boolean value saying if we should wake blocked writer threads |
660 | if( pushed == 1) | 671 | if (pushed.value() == 1) |
661 | { | 672 | { |
662 | ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); | 673 | ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); |
663 | linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area | 674 | linda->m_read_happened.notify_all(); // To be done from within the 'K' locking area |
@@ -667,10 +678,10 @@ LUAG_FUNC( linda_limit) | |||
667 | { | 678 | { |
668 | // do nothing and return lanes.cancel_error | 679 | // do nothing and return lanes.cancel_error |
669 | CANCEL_ERROR.pushKey(L); | 680 | CANCEL_ERROR.pushKey(L); |
670 | pushed = 1; | 681 | pushed.emplace(1); |
671 | } | 682 | } |
672 | // propagate pushed boolean if any | 683 | // propagate pushed boolean if any |
673 | return pushed; | 684 | return pushed.value(); |
674 | } | 685 | } |
675 | 686 | ||
676 | // ################################################################################################# | 687 | // ################################################################################################# |
@@ -682,7 +693,7 @@ LUAG_FUNC( linda_limit) | |||
682 | */ | 693 | */ |
683 | LUAG_FUNC(linda_cancel) | 694 | LUAG_FUNC(linda_cancel) |
684 | { | 695 | { |
685 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 696 | Linda* const linda{ ToLinda<false>(L, 1) }; |
686 | char const* who = luaL_optstring(L, 2, "both"); | 697 | char const* who = luaL_optstring(L, 2, "both"); |
687 | // make sure we got 3 arguments: the linda, a key and a limit | 698 | // make sure we got 3 arguments: the linda, a key and a limit |
688 | luaL_argcheck(L, lua_gettop(L) <= 2, 2, "wrong number of arguments"); | 699 | luaL_argcheck(L, lua_gettop(L) <= 2, 2, "wrong number of arguments"); |
@@ -726,7 +737,7 @@ LUAG_FUNC(linda_cancel) | |||
726 | */ | 737 | */ |
727 | LUAG_FUNC(linda_deep) | 738 | LUAG_FUNC(linda_deep) |
728 | { | 739 | { |
729 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 740 | Linda* const linda{ ToLinda<false>(L, 1) }; |
730 | lua_pushlightuserdata(L, linda); // just the address | 741 | lua_pushlightuserdata(L, linda); // just the address |
731 | return 1; | 742 | return 1; |
732 | } | 743 | } |
@@ -742,9 +753,9 @@ LUAG_FUNC(linda_deep) | |||
742 | */ | 753 | */ |
743 | 754 | ||
744 | template <bool OPT> | 755 | template <bool OPT> |
745 | [[nodiscard]] static int linda_tostring(lua_State* L, int idx_) | 756 | [[nodiscard]] static int LindaToString(lua_State* L, int idx_) |
746 | { | 757 | { |
747 | Linda* const linda{ lua_toLinda<OPT>(L, idx_) }; | 758 | Linda* const linda{ ToLinda<OPT>(L, idx_) }; |
748 | if (linda != nullptr) | 759 | if (linda != nullptr) |
749 | { | 760 | { |
750 | char text[128]; | 761 | char text[128]; |
@@ -761,7 +772,7 @@ template <bool OPT> | |||
761 | 772 | ||
762 | LUAG_FUNC(linda_tostring) | 773 | LUAG_FUNC(linda_tostring) |
763 | { | 774 | { |
764 | return linda_tostring<false>(L, 1); | 775 | return LindaToString<false>(L, 1); |
765 | } | 776 | } |
766 | 777 | ||
767 | // ################################################################################################# | 778 | // ################################################################################################# |
@@ -777,12 +788,12 @@ LUAG_FUNC(linda_concat) | |||
777 | { // linda1? linda2? | 788 | { // linda1? linda2? |
778 | bool atLeastOneLinda{ false }; | 789 | bool atLeastOneLinda{ false }; |
779 | // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. | 790 | // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. |
780 | if (linda_tostring<true>(L, 1)) | 791 | if (LindaToString<true>(L, 1)) |
781 | { | 792 | { |
782 | atLeastOneLinda = true; | 793 | atLeastOneLinda = true; |
783 | lua_replace(L, 1); | 794 | lua_replace(L, 1); |
784 | } | 795 | } |
785 | if (linda_tostring<true>(L, 2)) | 796 | if (LindaToString<true>(L, 2)) |
786 | { | 797 | { |
787 | atLeastOneLinda = true; | 798 | atLeastOneLinda = true; |
788 | lua_replace(L, 2); | 799 | lua_replace(L, 2); |
@@ -803,7 +814,7 @@ LUAG_FUNC(linda_concat) | |||
803 | */ | 814 | */ |
804 | LUAG_FUNC(linda_dump) | 815 | LUAG_FUNC(linda_dump) |
805 | { | 816 | { |
806 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 817 | Linda* const linda{ ToLinda<false>(L, 1) }; |
807 | return keeper_push_linda_storage(linda->U, Dest{ L }, linda, linda->hashSeed()); | 818 | return keeper_push_linda_storage(linda->U, Dest{ L }, linda, linda->hashSeed()); |
808 | } | 819 | } |
809 | 820 | ||
@@ -815,12 +826,12 @@ LUAG_FUNC(linda_dump) | |||
815 | */ | 826 | */ |
816 | LUAG_FUNC(linda_towatch) | 827 | LUAG_FUNC(linda_towatch) |
817 | { | 828 | { |
818 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 829 | Linda* const linda{ ToLinda<false>(L, 1) }; |
819 | int pushed{ keeper_push_linda_storage(linda->U, Dest{ L }, linda, linda->hashSeed()) }; | 830 | int pushed{ keeper_push_linda_storage(linda->U, Dest{ L }, linda, linda->hashSeed()) }; |
820 | if (pushed == 0) | 831 | if (pushed == 0) |
821 | { | 832 | { |
822 | // if the linda is empty, don't return nil | 833 | // if the linda is empty, don't return nil |
823 | pushed = linda_tostring<false>(L, 1); | 834 | pushed = LindaToString<false>(L, 1); |
824 | } | 835 | } |
825 | return pushed; | 836 | return pushed; |
826 | } | 837 | } |
@@ -907,7 +918,8 @@ LUAG_FUNC(linda_towatch) | |||
907 | // Clean associated structures in the keeper state. | 918 | // Clean associated structures in the keeper state. |
908 | Keeper* const K{ need_acquire_release ? keeper_acquire(linda->U->keepers, linda->hashSeed()) : myK }; | 919 | Keeper* const K{ need_acquire_release ? keeper_acquire(linda->U->keepers, linda->hashSeed()) : myK }; |
909 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | 920 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... |
910 | std::ignore = keeper_call(linda->U, K->L, KEEPER_API(clear), L, linda, 0); | 921 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(linda->U, K->L, KEEPER_API(clear), L, linda, 0) }; |
922 | ASSERT_L(result.has_value() && result.value() == 0); | ||
911 | if (need_acquire_release) | 923 | if (need_acquire_release) |
912 | { | 924 | { |
913 | keeper_release(K); | 925 | keeper_release(K); |
@@ -943,6 +955,7 @@ LUAG_FUNC(linda_towatch) | |||
943 | // protected calls, to ensure associated keeper is always released even in case of error | 955 | // protected calls, to ensure associated keeper is always released even in case of error |
944 | // all function are the protected call wrapper, where the actual operation is provided as upvalue | 956 | // all function are the protected call wrapper, where the actual operation is provided as upvalue |
945 | // note that this kind of thing can break function lookup as we use the function pointer here and there | 957 | // note that this kind of thing can break function lookup as we use the function pointer here and there |
958 | // TODO: change that and use different functions! | ||
946 | 959 | ||
947 | lua_pushcfunction(L, LG_linda_send); | 960 | lua_pushcfunction(L, LG_linda_send); |
948 | lua_pushcclosure(L, LG_linda_protected_call, 1); | 961 | lua_pushcclosure(L, LG_linda_protected_call, 1); |