aboutsummaryrefslogtreecommitdiff
path: root/src/linda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/linda.cpp')
-rw-r--r--src/linda.cpp29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/linda.cpp b/src/linda.cpp
index 079ab9d..f4dd7e7 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -452,21 +452,23 @@ LUAG_FUNC(linda_get)
452 452
453/* 453/*
454 * [bool]|nil,cancel_error = linda:limit(key_num|str|bool|lightuserdata, [int]) 454 * [bool]|nil,cancel_error = linda:limit(key_num|str|bool|lightuserdata, [int])
455 * "unlimited"|number = linda:limit(key)
455 * 456 *
456 * Set limit to 1 Linda keys. 457 * Read or set limit to 1 Linda keys.
457 * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so 458 * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so
458 * Limit can be 0 to completely block everything, nil to reset 459 * Limit can be 0 to completely block everything, "unlimited" to reset
459 */ 460 */
460LUAG_FUNC(linda_limit) 461LUAG_FUNC(linda_limit)
461{ 462{
462 static constexpr lua_CFunction _limit{ 463 static constexpr lua_CFunction _limit{
463 +[](lua_State* const L_) { 464 +[](lua_State* const L_) {
464 Linda* const _linda{ ToLinda<false>(L_, 1) }; 465 Linda* const _linda{ ToLinda<false>(L_, 1) };
465 // make sure we got 3 arguments: the linda, a key and a limit 466 // make sure we got 2 or 3 arguments: the linda, a key and optionally a limit
466 int const _nargs{ lua_gettop(L_) }; 467 int const _nargs{ lua_gettop(L_) };
467 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); 468 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments");
468 // make sure we got a numeric limit 469 // make sure we got a numeric limit, or "unlimited", (or nothing)
469 lua_Integer const _val{ luaL_optinteger(L_, 3, 0) }; 470 bool const _unlimited{ luaG_tostring(L_, 3) == "unlimited" };
471 LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : LindaLimit{ static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) } };
470 if (_val < 0) { 472 if (_val < 0) {
471 raise_luaL_argerror(L_, 3, "limit must be >= 0"); 473 raise_luaL_argerror(L_, 3, "limit must be >= 0");
472 } 474 }
@@ -476,10 +478,21 @@ LUAG_FUNC(linda_limit)
476 KeeperCallResult _pushed; 478 KeeperCallResult _pushed;
477 if (_linda->cancelRequest == CancelRequest::None) { 479 if (_linda->cancelRequest == CancelRequest::None) {
478 Keeper* const _keeper{ _linda->whichKeeper() }; 480 Keeper* const _keeper{ _linda->whichKeeper() };
481 if (_unlimited) {
482 LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaG_tostring(L_, 3) == "unlimited");
483 // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!)
484 lua_pop(L_, 1); // L_: linda key
485 lua_pushinteger(L_, -1); // L_: linda key nil
486 }
479 _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2); 487 _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2);
480 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1) && luaG_type(L_, -1) == LuaType::BOOLEAN); // no error, boolean value saying if we should wake blocked writer threads 488 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1));
481 if (lua_toboolean(L_, -1)) { 489 if (_nargs == 3) { // 3 args: setting the limit
482 _linda->readHappened.notify_all(); // To be done from within the 'K' locking area 490 LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::BOOLEAN); // changing the limit: no error, boolean value saying if we should wake blocked writer threads
491 if (lua_toboolean(L_, -1)) {
492 _linda->readHappened.notify_all(); // To be done from within the 'K' locking area
493 }
494 } else { // 2 args: reading the limit
495 LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER || luaG_tostring(L_, -1) == "unlimited"); // reading the limit: a number >=0 or "unlimited"
483 } 496 }
484 } else { // linda is cancelled 497 } else { // linda is cancelled
485 // do nothing and return nil,lanes.cancel_error 498 // do nothing and return nil,lanes.cancel_error